source: trunk/pgmodule.c @ 878

Last change on this file since 878 was 877, checked in by cito, 3 years ago

Fix issue with pg types with OID >= 0x80000000

  • Property svn:keywords set to Id
File size: 142.3 KB
Line 
1/*
2 * $Id: pgmodule.c 877 2016-07-16 09:36:09Z cito $
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 2016 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)) < 0)
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)) < 0)
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))
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))
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                char            **parms, **p;
2228                register int i;
2229
2230                str = (PyObject **)PyMem_Malloc(nparms * sizeof(*str));
2231                parms = (char **)PyMem_Malloc(nparms * sizeof(*parms));
2232                if (!str || !parms)
2233                {
2234                        PyMem_Free(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(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(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, (const char * const *)parms, NULL, NULL, 0);
2292                Py_END_ALLOW_THREADS
2293
2294                PyMem_Free(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                                                PQclear(result);
2342                                                if (ret[0])             /* return number of rows affected */
2343                                                {
2344                                                        return PyStr_FromString(ret);
2345                                                }
2346                                                Py_INCREF(Py_None);
2347                                                return Py_None;
2348                                        }
2349                                        /* for a single insert, return the oid */
2350                                        PQclear(result);
2351                                        return PyInt_FromLong(oid);
2352                                }
2353                        case PGRES_COPY_OUT:            /* no data will be received */
2354                        case PGRES_COPY_IN:
2355                                PQclear(result);
2356                                Py_INCREF(Py_None);
2357                                return Py_None;
2358                        default:
2359                                set_error_msg(InternalError, "Unknown result status");
2360                }
2361
2362                PQclear(result);
2363                return NULL;                    /* error detected on query */
2364        }
2365
2366        if (!(npgobj = PyObject_NEW(queryObject, &queryType)))
2367                return PyErr_NoMemory();
2368
2369        /* stores result and returns object */
2370        Py_XINCREF(self);
2371        npgobj->pgcnx = self;
2372        npgobj->result = result;
2373        npgobj->encoding = encoding;
2374        return (PyObject *) npgobj;
2375}
2376
2377#ifdef DIRECT_ACCESS
2378static char connPutLine__doc__[] =
2379"putline(line) -- send a line directly to the backend";
2380
2381/* direct access function: putline */
2382static PyObject *
2383connPutLine(connObject *self, PyObject *args)
2384{
2385        char *line;
2386        int line_length;
2387
2388        if (!self->cnx)
2389        {
2390                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2391                return NULL;
2392        }
2393
2394        /* reads args */
2395        if (!PyArg_ParseTuple(args, "s#", &line, &line_length))
2396        {
2397                PyErr_SetString(PyExc_TypeError,
2398                        "Method putline() takes a string argument");
2399                return NULL;
2400        }
2401
2402        /* sends line to backend */
2403        if (PQputline(self->cnx, line))
2404        {
2405                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2406                return NULL;
2407        }
2408        Py_INCREF(Py_None);
2409        return Py_None;
2410}
2411
2412/* direct access function: getline */
2413static char connGetLine__doc__[] =
2414"getline() -- get a line directly from the backend";
2415
2416static PyObject *
2417connGetLine(connObject *self, PyObject *noargs)
2418{
2419        char            line[MAX_BUFFER_SIZE];
2420        PyObject   *str = NULL;         /* GCC */
2421
2422        if (!self->cnx)
2423        {
2424                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2425                return NULL;
2426        }
2427
2428        /* gets line */
2429        switch (PQgetline(self->cnx, line, MAX_BUFFER_SIZE))
2430        {
2431                case 0:
2432                        str = PyStr_FromString(line);
2433                        break;
2434                case 1:
2435                        PyErr_SetString(PyExc_MemoryError, "Buffer overflow");
2436                        str = NULL;
2437                        break;
2438                case EOF:
2439                        Py_INCREF(Py_None);
2440                        str = Py_None;
2441                        break;
2442        }
2443
2444        return str;
2445}
2446
2447/* direct access function: end copy */
2448static char connEndCopy__doc__[] =
2449"endcopy() -- synchronize client and server";
2450
2451static PyObject *
2452connEndCopy(connObject *self, PyObject *noargs)
2453{
2454        if (!self->cnx)
2455        {
2456                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2457                return NULL;
2458        }
2459
2460        /* ends direct copy */
2461        if (PQendcopy(self->cnx))
2462        {
2463                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2464                return NULL;
2465        }
2466        Py_INCREF(Py_None);
2467        return Py_None;
2468}
2469#endif /* DIRECT_ACCESS */
2470
2471/* return query as string in human readable form */
2472static PyObject *
2473queryStr(queryObject *self)
2474{
2475        return format_result(self->result);
2476}
2477
2478/* insert table */
2479static char connInsertTable__doc__[] =
2480"inserttable(table, data) -- insert list into table\n\n"
2481"The fields in the list must be in the same order as in the table.\n";
2482
2483static PyObject *
2484connInsertTable(connObject *self, PyObject *args)
2485{
2486        PGresult        *result;
2487        char            *table,
2488                                *buffer,
2489                                *bufpt;
2490        int                     encoding;
2491        size_t          bufsiz;
2492        PyObject        *list,
2493                                *sublist,
2494                                *item;
2495        PyObject        *(*getitem) (PyObject *, Py_ssize_t);
2496        PyObject        *(*getsubitem) (PyObject *, Py_ssize_t);
2497        Py_ssize_t      i,
2498                                j,
2499                                m,
2500                                n;
2501
2502        if (!self->cnx)
2503        {
2504                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2505                return NULL;
2506        }
2507
2508        /* gets arguments */
2509        if (!PyArg_ParseTuple(args, "sO:filter", &table, &list))
2510        {
2511                PyErr_SetString(PyExc_TypeError,
2512                        "Method inserttable() expects a string and a list as arguments");
2513                return NULL;
2514        }
2515
2516        /* checks list type */
2517        if (PyTuple_Check(list))
2518        {
2519                m = PyTuple_Size(list);
2520                getitem = PyTuple_GetItem;
2521        }
2522        else if (PyList_Check(list))
2523        {
2524                m = PyList_Size(list);
2525                getitem = PyList_GetItem;
2526        }
2527        else
2528        {
2529                PyErr_SetString(PyExc_TypeError,
2530                        "Method inserttable() expects some kind of array"
2531                        " as second argument");
2532                return NULL;
2533        }
2534
2535        /* allocate buffer */
2536        if (!(buffer = PyMem_Malloc(MAX_BUFFER_SIZE)))
2537                return PyErr_NoMemory();
2538
2539        /* starts query */
2540        sprintf(buffer, "copy %s from stdin", table);
2541
2542        Py_BEGIN_ALLOW_THREADS
2543        result = PQexec(self->cnx, buffer);
2544        Py_END_ALLOW_THREADS
2545
2546        if (!result)
2547        {
2548                PyMem_Free(buffer);
2549                PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
2550                return NULL;
2551        }
2552
2553        encoding = PQclientEncoding(self->cnx);
2554
2555        PQclear(result);
2556
2557        n = 0; /* not strictly necessary but avoids warning */
2558
2559        /* feed table */
2560        for (i = 0; i < m; ++i)
2561        {
2562                sublist = getitem(list, i);
2563                if (PyTuple_Check(sublist))
2564                {
2565                        j = PyTuple_Size(sublist);
2566                        getsubitem = PyTuple_GetItem;
2567                }
2568                else if (PyList_Check(sublist))
2569                {
2570                        j = PyList_Size(sublist);
2571                        getsubitem = PyList_GetItem;
2572                }
2573                else
2574                {
2575                        PyErr_SetString(PyExc_TypeError,
2576                                "Second arg must contain some kind of arrays");
2577                        return NULL;
2578                }
2579                if (i)
2580                {
2581                        if (j != n)
2582                        {
2583                                PyMem_Free(buffer);
2584                                PyErr_SetString(PyExc_TypeError,
2585                                        "Arrays contained in second arg must have same size");
2586                                return NULL;
2587                        }
2588                }
2589                else
2590                {
2591                        n = j; /* never used before this assignment */
2592                }
2593
2594                /* builds insert line */
2595                bufpt = buffer;
2596                bufsiz = MAX_BUFFER_SIZE - 1;
2597
2598                for (j = 0; j < n; ++j)
2599                {
2600                        if (j)
2601                        {
2602                                *bufpt++ = '\t'; --bufsiz;
2603                        }
2604
2605                        item = getsubitem(sublist, j);
2606
2607                        /* convert item to string and append to buffer */
2608                        if (item == Py_None)
2609                        {
2610                                if (bufsiz > 2)
2611                                {
2612                                        *bufpt++ = '\\'; *bufpt++ = 'N';
2613                                        bufsiz -= 2;
2614                                }
2615                                else
2616                                        bufsiz = 0;
2617                        }
2618                        else if (PyBytes_Check(item))
2619                        {
2620                                const char* t = PyBytes_AsString(item);
2621                                while (*t && bufsiz)
2622                                {
2623                                        if (*t == '\\' || *t == '\t' || *t == '\n')
2624                                        {
2625                                                *bufpt++ = '\\'; --bufsiz;
2626                                                if (!bufsiz) break;
2627                                        }
2628                                        *bufpt++ = *t++; --bufsiz;
2629                                }
2630                        }
2631                        else if (PyUnicode_Check(item))
2632                        {
2633                                PyObject *s = get_encoded_string(item, encoding);
2634                                if (!s)
2635                                {
2636                                        PyMem_Free(buffer);
2637                                        return NULL; /* pass the UnicodeEncodeError */
2638                                }
2639                                else
2640                                {
2641                                        const char* t = PyBytes_AsString(s);
2642                                        while (*t && bufsiz)
2643                                        {
2644                                                if (*t == '\\' || *t == '\t' || *t == '\n')
2645                                                {
2646                                                        *bufpt++ = '\\'; --bufsiz;
2647                                                        if (!bufsiz) break;
2648                                                }
2649                                                *bufpt++ = *t++; --bufsiz;
2650                                        }
2651                                        Py_DECREF(s);
2652                                }
2653                        }
2654                        else if (PyInt_Check(item) || PyLong_Check(item))
2655                        {
2656                                PyObject* s = PyObject_Str(item);
2657                                const char* t = PyStr_AsString(s);
2658                                while (*t && bufsiz)
2659                                {
2660                                        *bufpt++ = *t++; --bufsiz;
2661                                }
2662                                Py_DECREF(s);
2663                        }
2664                        else
2665                        {
2666                                PyObject* s = PyObject_Repr(item);
2667                                const char* t = PyStr_AsString(s);
2668                                while (*t && bufsiz)
2669                                {
2670                                        if (*t == '\\' || *t == '\t' || *t == '\n')
2671                                        {
2672                                                *bufpt++ = '\\'; --bufsiz;
2673                                                if (!bufsiz) break;
2674                                        }
2675                                        *bufpt++ = *t++; --bufsiz;
2676                                }
2677                                Py_DECREF(s);
2678                        }
2679
2680                        if (bufsiz <= 0)
2681                        {
2682                                PyMem_Free(buffer); return PyErr_NoMemory();
2683                        }
2684
2685                }
2686
2687                *bufpt++ = '\n'; *bufpt = '\0';
2688
2689                /* sends data */
2690                if (PQputline(self->cnx, buffer))
2691                {
2692                        PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2693                        PQendcopy(self->cnx);
2694                        PyMem_Free(buffer);
2695                        return NULL;
2696                }
2697        }
2698
2699        /* ends query */
2700        if (PQputline(self->cnx, "\\.\n"))
2701        {
2702                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2703                PQendcopy(self->cnx);
2704                PyMem_Free(buffer);
2705                return NULL;
2706        }
2707
2708        if (PQendcopy(self->cnx))
2709        {
2710                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2711                PyMem_Free(buffer);
2712                return NULL;
2713        }
2714
2715        PyMem_Free(buffer);
2716
2717        /* no error : returns nothing */
2718        Py_INCREF(Py_None);
2719        return Py_None;
2720}
2721
2722/* get transaction state */
2723static char connTransaction__doc__[] =
2724"transaction() -- return the current transaction status";
2725
2726static PyObject *
2727connTransaction(connObject *self, PyObject *noargs)
2728{
2729        if (!self->cnx)
2730        {
2731                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2732                return NULL;
2733        }
2734
2735        return PyInt_FromLong(PQtransactionStatus(self->cnx));
2736}
2737
2738/* get parameter setting */
2739static char connParameter__doc__[] =
2740"parameter(name) -- look up a current parameter setting";
2741
2742static PyObject *
2743connParameter(connObject *self, PyObject *args)
2744{
2745        const char *name;
2746
2747        if (!self->cnx)
2748        {
2749                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2750                return NULL;
2751        }
2752
2753        /* get query args */
2754        if (!PyArg_ParseTuple(args, "s", &name))
2755        {
2756                PyErr_SetString(PyExc_TypeError,
2757                        "Method parameter() takes a string as argument");
2758                return NULL;
2759        }
2760
2761        name = PQparameterStatus(self->cnx, name);
2762
2763        if (name)
2764                return PyStr_FromString(name);
2765
2766        /* unknown parameter, return None */
2767        Py_INCREF(Py_None);
2768        return Py_None;
2769}
2770
2771/* internal function converting a Postgres datestyles to date formats */
2772static const char *
2773date_style_to_format(const char *s)
2774{
2775        static const char *formats[] = {
2776                "%Y-%m-%d",             /* 0 = ISO */
2777                "%m-%d-%Y",             /* 1 = Postgres, MDY */
2778                "%d-%m-%Y",             /* 2 = Postgres, DMY */
2779                "%m/%d/%Y",             /* 3 = SQL, MDY */
2780                "%d/%m/%Y",             /* 4 = SQL, DMY */
2781                "%d.%m.%Y"};    /* 5 = German */
2782
2783        switch (s ? *s : 'I')
2784        {
2785                case 'P': /* Postgres */
2786                        s = strchr(s + 1, ',');
2787                        if (s) do ++s; while (*s && *s == ' ');
2788                        return formats[s && *s == 'D' ? 2 : 1];
2789                case 'S': /* SQL */
2790                        s = strchr(s + 1, ',');
2791                        if (s) do ++s; while (*s && *s == ' ');
2792                        return formats[s && *s == 'D' ? 4 : 3];
2793                case 'G': /* German */
2794                        return formats[5];
2795                default: /* ISO */
2796                        return formats[0]; /* ISO is the default */
2797        }
2798}
2799
2800/* internal function converting a date format to a Postgres datestyle */
2801static const char *
2802date_format_to_style(const char *s)
2803{
2804        static const char *datestyle[] = {
2805                "ISO, YMD",                     /* 0 = %Y-%m-%d */
2806                "Postgres, MDY",        /* 1 = %m-%d-%Y */
2807                "Postgres, DMY",        /* 2 = %d-%m-%Y */
2808                "SQL, MDY",             /* 3 = %m/%d/%Y */
2809                "SQL, DMY",             /* 4 = %d/%m/%Y */
2810                "German, DMY"};         /* 5 = %d.%m.%Y */
2811
2812        switch (s ? s[1] : 'Y')
2813        {
2814                case 'm':
2815                        switch (s[2])
2816                        {
2817                                case '/':
2818                                        return datestyle[3]; /* SQL, MDY */
2819                                default:
2820                                        return datestyle[1]; /* Postgres, MDY */
2821                        }
2822                case 'd':
2823                        switch (s[2])
2824                        {
2825                                case '/':
2826                                        return datestyle[4]; /* SQL, DMY */
2827                                case '.':
2828                                        return datestyle[5]; /* German */
2829                                default:
2830                                        return datestyle[2]; /* Postgres, DMY */
2831                        }
2832                default:
2833                        return datestyle[0]; /* ISO */
2834        }
2835}
2836
2837/* get current date format */
2838static char connDateFormat__doc__[] =
2839"date_format() -- return the current date format";
2840
2841static PyObject *
2842connDateFormat(connObject *self, PyObject *noargs)
2843{
2844        const char *fmt;
2845
2846        if (!self->cnx)
2847        {
2848                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
2849                return NULL;
2850        }
2851
2852        /* check if the date format is cached in the connection */
2853        fmt = self->date_format;
2854        if (!fmt)
2855        {
2856                fmt = date_style_to_format(PQparameterStatus(self->cnx, "DateStyle"));
2857                self->date_format = fmt; /* cache the result */
2858        }
2859
2860        return PyStr_FromString(fmt);
2861}
2862
2863#ifdef ESCAPING_FUNCS
2864
2865/* escape literal */
2866static char connEscapeLiteral__doc__[] =
2867"escape_literal(str) -- escape a literal constant for use within SQL";
2868
2869static PyObject *
2870connEscapeLiteral(connObject *self, PyObject *string)
2871{
2872        PyObject   *tmp_obj = NULL, /* auxiliary string object */
2873                           *to_obj; /* string object to return */
2874        char       *from, /* our string argument as encoded string */
2875                           *to; /* the result as encoded string */
2876        Py_ssize_t      from_length; /* length of string */
2877        size_t          to_length; /* length of result */
2878        int                     encoding = -1; /* client encoding */
2879
2880        if (PyBytes_Check(string))
2881        {
2882                PyBytes_AsStringAndSize(string, &from, &from_length);
2883        }
2884        else if (PyUnicode_Check(string))
2885        {
2886                encoding = PQclientEncoding(self->cnx);
2887                tmp_obj = get_encoded_string(string, encoding);
2888                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
2889                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
2890        }
2891        else
2892        {
2893                PyErr_SetString(PyExc_TypeError,
2894                        "Method escape_literal() expects a string as argument");
2895                return NULL;
2896        }
2897
2898        to = PQescapeLiteral(self->cnx, from, (size_t)from_length);
2899        to_length = strlen(to);
2900
2901        Py_XDECREF(tmp_obj);
2902
2903        if (encoding == -1)
2904                to_obj = PyBytes_FromStringAndSize(to, to_length);
2905        else
2906                to_obj = get_decoded_string(to, to_length, encoding);
2907        if (to)
2908                PQfreemem(to);
2909        return to_obj;
2910}
2911
2912/* escape identifier */
2913static char connEscapeIdentifier__doc__[] =
2914"escape_identifier(str) -- escape an identifier for use within SQL";
2915
2916static PyObject *
2917connEscapeIdentifier(connObject *self, PyObject *string)
2918{
2919        PyObject   *tmp_obj = NULL, /* auxiliary string object */
2920                           *to_obj; /* string object to return */
2921        char       *from, /* our string argument as encoded string */
2922                           *to; /* the result as encoded string */
2923        Py_ssize_t      from_length; /* length of string */
2924        size_t          to_length; /* length of result */
2925        int                     encoding = -1; /* client encoding */
2926
2927        if (PyBytes_Check(string))
2928        {
2929                PyBytes_AsStringAndSize(string, &from, &from_length);
2930        }
2931        else if (PyUnicode_Check(string))
2932        {
2933                encoding = PQclientEncoding(self->cnx);
2934                tmp_obj = get_encoded_string(string, encoding);
2935                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
2936                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
2937        }
2938        else
2939        {
2940                PyErr_SetString(PyExc_TypeError,
2941                        "Method escape_identifier() expects a string as argument");
2942                return NULL;
2943        }
2944
2945        to = PQescapeIdentifier(self->cnx, from, (size_t)from_length);
2946        to_length = strlen(to);
2947
2948        Py_XDECREF(tmp_obj);
2949
2950        if (encoding == -1)
2951                to_obj = PyBytes_FromStringAndSize(to, to_length);
2952        else
2953                to_obj = get_decoded_string(to, to_length, encoding);
2954        if (to)
2955                PQfreemem(to);
2956        return to_obj;
2957}
2958
2959#endif  /* ESCAPING_FUNCS */
2960
2961/* escape string */
2962static char connEscapeString__doc__[] =
2963"escape_string(str) -- escape a string for use within SQL";
2964
2965static PyObject *
2966connEscapeString(connObject *self, PyObject *string)
2967{
2968        PyObject   *tmp_obj = NULL, /* auxiliary string object */
2969                           *to_obj; /* string object to return */
2970        char       *from, /* our string argument as encoded string */
2971                           *to; /* the result as encoded string */
2972        Py_ssize_t      from_length; /* length of string */
2973        size_t          to_length; /* length of result */
2974        int                     encoding = -1; /* client encoding */
2975
2976        if (PyBytes_Check(string))
2977        {
2978                PyBytes_AsStringAndSize(string, &from, &from_length);
2979        }
2980        else if (PyUnicode_Check(string))
2981        {
2982                encoding = PQclientEncoding(self->cnx);
2983                tmp_obj = get_encoded_string(string, encoding);
2984                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
2985                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
2986        }
2987        else
2988        {
2989                PyErr_SetString(PyExc_TypeError,
2990                        "Method escape_string() expects a string as argument");
2991                return NULL;
2992        }
2993
2994        to_length = 2*from_length + 1;
2995        if ((Py_ssize_t)to_length < from_length) /* overflow */
2996        {
2997                to_length = from_length;
2998                from_length = (from_length - 1)/2;
2999        }
3000        to = (char *)PyMem_Malloc(to_length);
3001        to_length = PQescapeStringConn(self->cnx,
3002                to, from, (size_t)from_length, NULL);
3003
3004        Py_XDECREF(tmp_obj);
3005
3006        if (encoding == -1)
3007                to_obj = PyBytes_FromStringAndSize(to, to_length);
3008        else
3009                to_obj = get_decoded_string(to, to_length, encoding);
3010        PyMem_Free(to);
3011        return to_obj;
3012}
3013
3014/* escape bytea */
3015static char connEscapeBytea__doc__[] =
3016"escape_bytea(data) -- escape binary data for use within SQL as type bytea";
3017
3018static PyObject *
3019connEscapeBytea(connObject *self, PyObject *data)
3020{
3021        PyObject   *tmp_obj = NULL, /* auxiliary string object */
3022                           *to_obj; /* string object to return */
3023        char       *from, /* our string argument as encoded string */
3024                           *to; /* the result as encoded string */
3025        Py_ssize_t      from_length; /* length of string */
3026        size_t          to_length; /* length of result */
3027        int                     encoding = -1; /* client encoding */
3028
3029        if (PyBytes_Check(data))
3030        {
3031                PyBytes_AsStringAndSize(data, &from, &from_length);
3032        }
3033        else if (PyUnicode_Check(data))
3034        {
3035                encoding = PQclientEncoding(self->cnx);
3036                tmp_obj = get_encoded_string(data, encoding);
3037                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
3038                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
3039        }
3040        else
3041        {
3042                PyErr_SetString(PyExc_TypeError,
3043                        "Method escape_bytea() expects a string as argument");
3044                return NULL;
3045        }
3046
3047        to = (char *)PQescapeByteaConn(self->cnx,
3048                (unsigned char *)from, (size_t)from_length, &to_length);
3049
3050        Py_XDECREF(tmp_obj);
3051
3052        if (encoding == -1)
3053                to_obj = PyBytes_FromStringAndSize(to, to_length - 1);
3054        else
3055                to_obj = get_decoded_string(to, to_length - 1, encoding);
3056        if (to)
3057                PQfreemem(to);
3058        return to_obj;
3059}
3060
3061#ifdef LARGE_OBJECTS
3062/* creates large object */
3063static char connCreateLO__doc__[] =
3064"locreate(mode) -- create a new large object in the database";
3065
3066static PyObject *
3067connCreateLO(connObject *self, PyObject *args)
3068{
3069        int                     mode;
3070        Oid                     lo_oid;
3071
3072        /* checks validity */
3073        if (!check_cnx_obj(self))
3074                return NULL;
3075
3076        /* gets arguments */
3077        if (!PyArg_ParseTuple(args, "i", &mode))
3078        {
3079                PyErr_SetString(PyExc_TypeError,
3080                        "Method locreate() takes an integer argument");
3081                return NULL;
3082        }
3083
3084        /* creates large object */
3085        lo_oid = lo_creat(self->cnx, mode);
3086        if (lo_oid == 0)
3087        {
3088                set_error_msg(OperationalError, "Can't create large object");
3089                return NULL;
3090        }
3091
3092        return (PyObject *) largeNew(self, lo_oid);
3093}
3094
3095/* init from already known oid */
3096static char connGetLO__doc__[] =
3097"getlo(oid) -- create a large object instance for the specified oid";
3098
3099static PyObject *
3100connGetLO(connObject *self, PyObject *args)
3101{
3102        int                     lo_oid;
3103
3104        /* checks validity */
3105        if (!check_cnx_obj(self))
3106                return NULL;
3107
3108        /* gets arguments */
3109        if (!PyArg_ParseTuple(args, "i", &lo_oid))
3110        {
3111                PyErr_SetString(PyExc_TypeError,
3112                        "Method getlo() takes an integer argument");
3113                return NULL;
3114        }
3115
3116        if (!lo_oid)
3117        {
3118                PyErr_SetString(PyExc_ValueError, "The object oid can't be null");
3119                return NULL;
3120        }
3121
3122        /* creates object */
3123        return (PyObject *) largeNew(self, lo_oid);
3124}
3125
3126/* import unix file */
3127static char connImportLO__doc__[] =
3128"loimport(name) -- create a new large object from specified file";
3129
3130static PyObject *
3131connImportLO(connObject *self, PyObject *args)
3132{
3133        char   *name;
3134        Oid             lo_oid;
3135
3136        /* checks validity */
3137        if (!check_cnx_obj(self))
3138                return NULL;
3139
3140        /* gets arguments */
3141        if (!PyArg_ParseTuple(args, "s", &name))
3142        {
3143                PyErr_SetString(PyExc_TypeError,
3144                        "Method loimport() takes a string argument");
3145                return NULL;
3146        }
3147
3148        /* imports file and checks result */
3149        lo_oid = lo_import(self->cnx, name);
3150        if (lo_oid == 0)
3151        {
3152                set_error_msg(OperationalError, "Can't create large object");
3153                return NULL;
3154        }
3155
3156        return (PyObject *) largeNew(self, lo_oid);
3157}
3158#endif /* LARGE_OBJECTS */
3159
3160/* resets connection */
3161static char connReset__doc__[] =
3162"reset() -- reset connection with current parameters\n\n"
3163"All derived queries and large objects derived from this connection\n"
3164"will not be usable after this call.\n";
3165
3166static PyObject *
3167connReset(connObject *self, PyObject *noargs)
3168{
3169        if (!self->cnx)
3170        {
3171                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3172                return NULL;
3173        }
3174
3175        /* resets the connection */
3176        PQreset(self->cnx);
3177        Py_INCREF(Py_None);
3178        return Py_None;
3179}
3180
3181/* cancels current command */
3182static char connCancel__doc__[] =
3183"cancel() -- abandon processing of the current command";
3184
3185static PyObject *
3186connCancel(connObject *self, PyObject *noargs)
3187{
3188        if (!self->cnx)
3189        {
3190                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3191                return NULL;
3192        }
3193
3194        /* request that the server abandon processing of the current command */
3195        return PyInt_FromLong((long) PQrequestCancel(self->cnx));
3196}
3197
3198/* get connection socket */
3199static char connFileno__doc__[] =
3200"fileno() -- return database connection socket file handle";
3201
3202static PyObject *
3203connFileno(connObject *self, PyObject *noargs)
3204{
3205        if (!self->cnx)
3206        {
3207                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3208                return NULL;
3209        }
3210
3211#ifdef NO_PQSOCKET
3212        return PyInt_FromLong((long) self->cnx->sock);
3213#else
3214        return PyInt_FromLong((long) PQsocket(self->cnx));
3215#endif
3216}
3217
3218/* set external typecast callback function */
3219static char connSetCastHook__doc__[] =
3220"set_cast_hook(func) -- set a fallback typecast function";
3221
3222static PyObject *
3223connSetCastHook(connObject *self, PyObject *func)
3224{
3225        PyObject *ret = NULL;
3226
3227        if (func == Py_None)
3228        {
3229                Py_XDECREF(self->cast_hook);
3230                self->cast_hook = NULL;
3231                Py_INCREF(Py_None); ret = Py_None;
3232        }
3233        else if (PyCallable_Check(func))
3234        {
3235                Py_XINCREF(func); Py_XDECREF(self->cast_hook);
3236                self->cast_hook = func;
3237                Py_INCREF(Py_None); ret = Py_None;
3238        }
3239        else
3240                PyErr_SetString(PyExc_TypeError,
3241                        "Method set_cast_hook() expects"
3242                         " a callable or None as argument");
3243
3244        return ret;
3245}
3246
3247/* get notice receiver callback function */
3248static char connGetCastHook__doc__[] =
3249"get_cast_hook() -- get the fallback typecast function";
3250
3251static PyObject *
3252connGetCastHook(connObject *self, PyObject *noargs)
3253{
3254        PyObject *ret = self->cast_hook;;
3255
3256        if (!ret)
3257                ret = Py_None;
3258        Py_INCREF(ret);
3259
3260        return ret;
3261}
3262
3263/* set notice receiver callback function */
3264static char connSetNoticeReceiver__doc__[] =
3265"set_notice_receiver(func) -- set the current notice receiver";
3266
3267static PyObject *
3268connSetNoticeReceiver(connObject *self, PyObject *func)
3269{
3270        PyObject *ret = NULL;
3271
3272        if (func == Py_None)
3273        {
3274                Py_XDECREF(self->notice_receiver);
3275                self->notice_receiver = NULL;
3276                Py_INCREF(Py_None); ret = Py_None;
3277        }
3278        else if (PyCallable_Check(func))
3279        {
3280                Py_XINCREF(func); Py_XDECREF(self->notice_receiver);
3281                self->notice_receiver = func;
3282                PQsetNoticeReceiver(self->cnx, notice_receiver, self);
3283                Py_INCREF(Py_None); ret = Py_None;
3284        }
3285        else
3286                PyErr_SetString(PyExc_TypeError,
3287                        "Method set_notice_receiver() expects"
3288                         " a callable or None as argument");
3289
3290        return ret;
3291}
3292
3293/* get notice receiver callback function */
3294static char connGetNoticeReceiver__doc__[] =
3295"get_notice_receiver() -- get the current notice receiver";
3296
3297static PyObject *
3298connGetNoticeReceiver(connObject *self, PyObject *noargs)
3299{
3300        PyObject *ret = self->notice_receiver;
3301
3302        if (!ret)
3303                ret = Py_None;
3304        Py_INCREF(ret);
3305
3306        return ret;
3307}
3308
3309/* close without deleting */
3310static char connClose__doc__[] =
3311"close() -- close connection\n\n"
3312"All instances of the connection object and derived objects\n"
3313"(queries and large objects) can no longer be used after this call.\n";
3314
3315static PyObject *
3316connClose(connObject *self, PyObject *noargs)
3317{
3318        /* connection object cannot already be closed */
3319        if (!self->cnx)
3320        {
3321                set_error_msg(InternalError, "Connection already closed");
3322                return NULL;
3323        }
3324
3325        Py_BEGIN_ALLOW_THREADS
3326        PQfinish(self->cnx);
3327        Py_END_ALLOW_THREADS
3328
3329        self->cnx = NULL;
3330        Py_INCREF(Py_None);
3331        return Py_None;
3332}
3333
3334/* gets asynchronous notify */
3335static char connGetNotify__doc__[] =
3336"getnotify() -- get database notify for this connection";
3337
3338static PyObject *
3339connGetNotify(connObject *self, PyObject *noargs)
3340{
3341        PGnotify   *notify;
3342
3343        if (!self->cnx)
3344        {
3345                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3346                return NULL;
3347        }
3348
3349        /* checks for NOTIFY messages */
3350        PQconsumeInput(self->cnx);
3351
3352        if (!(notify = PQnotifies(self->cnx)))
3353        {
3354                Py_INCREF(Py_None);
3355                return Py_None;
3356        }
3357        else
3358        {
3359                PyObject   *notify_result,
3360                                   *temp;
3361
3362                if (!(temp = PyStr_FromString(notify->relname)))
3363                        return NULL;
3364
3365                if (!(notify_result = PyTuple_New(3)))
3366                        return NULL;
3367
3368                PyTuple_SET_ITEM(notify_result, 0, temp);
3369
3370                if (!(temp = PyInt_FromLong(notify->be_pid)))
3371                {
3372                        Py_DECREF(notify_result);
3373                        return NULL;
3374                }
3375
3376                PyTuple_SET_ITEM(notify_result, 1, temp);
3377
3378                /* extra exists even in old versions that did not support it */
3379                if (!(temp = PyStr_FromString(notify->extra)))
3380                {
3381                        Py_DECREF(notify_result);
3382                        return NULL;
3383                }
3384
3385                PyTuple_SET_ITEM(notify_result, 2, temp);
3386
3387                PQfreemem(notify);
3388
3389                return notify_result;
3390        }
3391}
3392
3393/* get the list of connection attributes */
3394static PyObject *
3395connDir(connObject *self, PyObject *noargs)
3396{
3397        PyObject *attrs;
3398
3399        attrs = PyObject_Dir(PyObject_Type((PyObject *)self));
3400        PyObject_CallMethod(attrs, "extend", "[sssssssss]",
3401                "host", "port", "db", "options", "error", "status", "user",
3402                "protocol_version", "server_version");
3403
3404        return attrs;
3405}
3406
3407/* connection object methods */
3408static struct PyMethodDef connMethods[] = {
3409        {"__dir__", (PyCFunction) connDir,  METH_NOARGS, NULL},
3410
3411        {"source", (PyCFunction) connSource, METH_NOARGS, connSource__doc__},
3412        {"query", (PyCFunction) connQuery, METH_VARARGS, connQuery__doc__},
3413        {"reset", (PyCFunction) connReset, METH_NOARGS, connReset__doc__},
3414        {"cancel", (PyCFunction) connCancel, METH_NOARGS, connCancel__doc__},
3415        {"close", (PyCFunction) connClose, METH_NOARGS, connClose__doc__},
3416        {"fileno", (PyCFunction) connFileno, METH_NOARGS, connFileno__doc__},
3417        {"get_cast_hook", (PyCFunction) connGetCastHook, METH_NOARGS,
3418                        connGetCastHook__doc__},
3419        {"set_cast_hook", (PyCFunction) connSetCastHook, METH_O,
3420                        connSetCastHook__doc__},
3421        {"get_notice_receiver", (PyCFunction) connGetNoticeReceiver, METH_NOARGS,
3422                        connGetNoticeReceiver__doc__},
3423        {"set_notice_receiver", (PyCFunction) connSetNoticeReceiver, METH_O,
3424                        connSetNoticeReceiver__doc__},
3425        {"getnotify", (PyCFunction) connGetNotify, METH_NOARGS,
3426                        connGetNotify__doc__},
3427        {"inserttable", (PyCFunction) connInsertTable, METH_VARARGS,
3428                        connInsertTable__doc__},
3429        {"transaction", (PyCFunction) connTransaction, METH_NOARGS,
3430                        connTransaction__doc__},
3431        {"parameter", (PyCFunction) connParameter, METH_VARARGS,
3432                        connParameter__doc__},
3433        {"date_format", (PyCFunction) connDateFormat, METH_NOARGS,
3434                        connDateFormat__doc__},
3435
3436#ifdef ESCAPING_FUNCS
3437        {"escape_literal", (PyCFunction) connEscapeLiteral, METH_O,
3438                        connEscapeLiteral__doc__},
3439        {"escape_identifier", (PyCFunction) connEscapeIdentifier, METH_O,
3440                        connEscapeIdentifier__doc__},
3441#endif  /* ESCAPING_FUNCS */
3442        {"escape_string", (PyCFunction) connEscapeString, METH_O,
3443                        connEscapeString__doc__},
3444        {"escape_bytea", (PyCFunction) connEscapeBytea, METH_O,
3445                        connEscapeBytea__doc__},
3446
3447#ifdef DIRECT_ACCESS
3448        {"putline", (PyCFunction) connPutLine, METH_VARARGS, connPutLine__doc__},
3449        {"getline", (PyCFunction) connGetLine, METH_NOARGS, connGetLine__doc__},
3450        {"endcopy", (PyCFunction) connEndCopy, METH_NOARGS, connEndCopy__doc__},
3451#endif /* DIRECT_ACCESS */
3452
3453#ifdef LARGE_OBJECTS
3454        {"locreate", (PyCFunction) connCreateLO, METH_VARARGS, connCreateLO__doc__},
3455        {"getlo", (PyCFunction) connGetLO, METH_VARARGS, connGetLO__doc__},
3456        {"loimport", (PyCFunction) connImportLO, METH_VARARGS, connImportLO__doc__},
3457#endif /* LARGE_OBJECTS */
3458
3459        {NULL, NULL} /* sentinel */
3460};
3461
3462/* gets connection attributes */
3463static PyObject *
3464connGetAttr(connObject *self, PyObject *nameobj)
3465{
3466        const char *name = PyStr_AsString(nameobj);
3467
3468        /*
3469         * Although we could check individually, there are only a few
3470         * attributes that don't require a live connection and unless someone
3471         * has an urgent need, this will have to do
3472         */
3473
3474        /* first exception - close which returns a different error */
3475        if (strcmp(name, "close") && !self->cnx)
3476        {
3477                PyErr_SetString(PyExc_TypeError, "Connection is not valid");
3478                return NULL;
3479        }
3480
3481        /* list PostgreSQL connection fields */
3482
3483        /* postmaster host */
3484        if (!strcmp(name, "host"))
3485        {
3486                char *r = PQhost(self->cnx);
3487                if (!r)
3488                        r = "localhost";
3489                return PyStr_FromString(r);
3490        }
3491
3492        /* postmaster port */
3493        if (!strcmp(name, "port"))
3494                return PyInt_FromLong(atol(PQport(self->cnx)));
3495
3496        /* selected database */
3497        if (!strcmp(name, "db"))
3498                return PyStr_FromString(PQdb(self->cnx));
3499
3500        /* selected options */
3501        if (!strcmp(name, "options"))
3502                return PyStr_FromString(PQoptions(self->cnx));
3503
3504        /* error (status) message */
3505        if (!strcmp(name, "error"))
3506                return PyStr_FromString(PQerrorMessage(self->cnx));
3507
3508        /* connection status : 1 - OK, 0 - BAD */
3509        if (!strcmp(name, "status"))
3510                return PyInt_FromLong(PQstatus(self->cnx) == CONNECTION_OK ? 1 : 0);
3511
3512        /* provided user name */
3513        if (!strcmp(name, "user"))
3514                return PyStr_FromString(PQuser(self->cnx));
3515
3516        /* protocol version */
3517        if (!strcmp(name, "protocol_version"))
3518                return PyInt_FromLong(PQprotocolVersion(self->cnx));
3519
3520        /* backend version */
3521        if (!strcmp(name, "server_version"))
3522                return PyInt_FromLong(PQserverVersion(self->cnx));
3523
3524        return PyObject_GenericGetAttr((PyObject *) self, nameobj);
3525}
3526
3527/* connection type definition */
3528static PyTypeObject connType = {
3529        PyVarObject_HEAD_INIT(NULL, 0)
3530        "pg.Connection",                        /* tp_name */
3531        sizeof(connObject),                     /* tp_basicsize */
3532        0,                                                      /* tp_itemsize */
3533        (destructor) connDelete,        /* tp_dealloc */
3534        0,                                                      /* tp_print */
3535        0,                                                      /* tp_getattr */
3536        0,                                                      /* tp_setattr */
3537        0,                                                      /* tp_reserved */
3538        0,                                                      /* tp_repr */
3539        0,                                                      /* tp_as_number */
3540        0,                                                      /* tp_as_sequence */
3541        0,                                                      /* tp_as_mapping */
3542        0,                                                      /* tp_hash */
3543        0,                                                      /* tp_call */
3544        0,                                                      /* tp_str */
3545        (getattrofunc) connGetAttr,     /* tp_getattro */
3546        0,                                                      /* tp_setattro */
3547        0,                                                      /* tp_as_buffer */
3548        Py_TPFLAGS_DEFAULT,                     /* tp_flags */
3549        0,                                                      /* tp_doc */
3550        0,                                                      /* tp_traverse */
3551        0,                                                      /* tp_clear */
3552        0,                                                      /* tp_richcompare */
3553        0,                                                      /* tp_weaklistoffset */
3554        0,                                                      /* tp_iter */
3555        0,                                                      /* tp_iternext */
3556        connMethods,                            /* tp_methods */
3557};
3558
3559/* --------------------------------------------------------------------- */
3560/* source object                                                                                                                 */
3561/* --------------------------------------------------------------------- */
3562/* checks source object validity */
3563static int
3564check_source_obj(sourceObject *self, int level)
3565{
3566        if (!self->valid)
3567        {
3568                set_error_msg(OperationalError, "Object has been closed");
3569                return 0;
3570        }
3571
3572        if ((level & CHECK_RESULT) && !self->result)
3573        {
3574                set_error_msg(DatabaseError, "No result");
3575                return 0;
3576        }
3577
3578        if ((level & CHECK_DQL) && self->result_type != RESULT_DQL)
3579        {
3580                set_error_msg(DatabaseError, "Last query did not return tuples");
3581                return 0;
3582        }
3583
3584        if ((level & CHECK_CNX) && !check_cnx_obj(self->pgcnx))
3585                return 0;
3586
3587        return 1;
3588}
3589
3590/* destructor */
3591static void
3592sourceDealloc(sourceObject *self)
3593{
3594        if (self->result)
3595                PQclear(self->result);
3596
3597        Py_XDECREF(self->pgcnx);
3598        PyObject_Del(self);
3599}
3600
3601/* closes object */
3602static char sourceClose__doc__[] =
3603"close() -- close query object without deleting it\n\n"
3604"All instances of the query object can no longer be used after this call.\n";
3605
3606static PyObject *
3607sourceClose(sourceObject *self, PyObject *noargs)
3608{
3609        /* frees result if necessary and invalidates object */
3610        if (self->result)
3611        {
3612                PQclear(self->result);
3613                self->result_type = RESULT_EMPTY;
3614                self->result = NULL;
3615        }
3616
3617        self->valid = 0;
3618
3619        /* return None */
3620        Py_INCREF(Py_None);
3621        return Py_None;
3622}
3623
3624/* database query */
3625static char sourceExecute__doc__[] =
3626"execute(sql) -- execute a SQL statement (string)\n\n"
3627"On success, this call returns the number of affected rows, or None\n"
3628"for DQL (SELECT, ...) statements.  The fetch (fetch(), fetchone()\n"
3629"and fetchall()) methods can be used to get result rows.\n";
3630
3631static PyObject *
3632sourceExecute(sourceObject *self, PyObject *sql)
3633{
3634        PyObject   *tmp_obj = NULL; /* auxiliary string object */
3635        char       *query;
3636        int                     encoding;
3637
3638        /* checks validity */
3639        if (!check_source_obj(self, CHECK_CNX))
3640                return NULL;
3641
3642        encoding = PQclientEncoding(self->pgcnx->cnx);
3643
3644        if (PyBytes_Check(sql))
3645        {
3646                query = PyBytes_AsString(sql);
3647        }
3648        else if (PyUnicode_Check(sql))
3649        {
3650                tmp_obj = get_encoded_string(sql, encoding);
3651                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
3652                query = PyBytes_AsString(tmp_obj);
3653        }
3654        else
3655        {
3656                PyErr_SetString(PyExc_TypeError,
3657                        "Method execute() expects a string as argument");
3658                return NULL;
3659        }
3660
3661        /* frees previous result */
3662        if (self->result)
3663        {
3664                PQclear(self->result);
3665                self->result = NULL;
3666        }
3667        self->max_row = 0;
3668        self->current_row = 0;
3669        self->num_fields = 0;
3670        self->encoding = encoding;
3671
3672        /* gets result */
3673        Py_BEGIN_ALLOW_THREADS
3674        self->result = PQexec(self->pgcnx->cnx, query);
3675        Py_END_ALLOW_THREADS
3676
3677        /* we don't need the auxiliary string any more */
3678        Py_XDECREF(tmp_obj);
3679
3680        /* checks result validity */
3681        if (!self->result)
3682        {
3683                PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->pgcnx->cnx));
3684                return NULL;
3685        }
3686
3687        /* this may have changed the datestyle, so we reset the date format
3688           in order to force fetching it newly when next time requested */
3689        self->pgcnx->date_format = date_format; /* this is normally NULL */
3690
3691        /* checks result status */
3692        switch (PQresultStatus(self->result))
3693        {
3694                long    num_rows;
3695                char   *temp;
3696
3697                /* query succeeded */
3698                case PGRES_TUPLES_OK:   /* DQL: returns None (DB-SIG compliant) */
3699                        self->result_type = RESULT_DQL;
3700                        self->max_row = PQntuples(self->result);
3701                        self->num_fields = PQnfields(self->result);
3702                        Py_INCREF(Py_None);
3703                        return Py_None;
3704                case PGRES_COMMAND_OK:  /* other requests */
3705                case PGRES_COPY_OUT:
3706                case PGRES_COPY_IN:
3707                        self->result_type = RESULT_DDL;
3708                        temp = PQcmdTuples(self->result);
3709                        num_rows = -1;
3710                        if (temp[0])
3711                        {
3712                                self->result_type = RESULT_DML;
3713                                num_rows = atol(temp);
3714                        }
3715                        return PyInt_FromLong(num_rows);
3716
3717                /* query failed */
3718                case PGRES_EMPTY_QUERY:
3719                        PyErr_SetString(PyExc_ValueError, "Empty query");
3720                        break;
3721                case PGRES_BAD_RESPONSE:
3722                case PGRES_FATAL_ERROR:
3723                case PGRES_NONFATAL_ERROR:
3724                        set_error(ProgrammingError, "Cannot execute command",
3725                                self->pgcnx->cnx, self->result);
3726                        break;
3727                default:
3728                        set_error_msg(InternalError, "Internal error: "
3729                                "unknown result status");
3730        }
3731
3732        /* frees result and returns error */
3733        PQclear(self->result);
3734        self->result = NULL;
3735        self->result_type = RESULT_EMPTY;
3736        return NULL;
3737}
3738
3739/* gets oid status for last query (valid for INSERTs, 0 for other) */
3740static char sourceStatusOID__doc__[] =
3741"oidstatus() -- return oid of last inserted row (if available)";
3742
3743static PyObject *
3744sourceStatusOID(sourceObject *self, PyObject *noargs)
3745{
3746        Oid                     oid;
3747
3748        /* checks validity */
3749        if (!check_source_obj(self, CHECK_RESULT))
3750                return NULL;
3751
3752        /* retrieves oid status */
3753        if ((oid = PQoidValue(self->result)) == InvalidOid)
3754        {
3755                Py_INCREF(Py_None);
3756                return Py_None;
3757        }
3758
3759        return PyInt_FromLong(oid);
3760}
3761
3762/* fetches rows from last result */
3763static char sourceFetch__doc__[] =
3764"fetch(num) -- return the next num rows from the last result in a list\n\n"
3765"If num parameter is omitted arraysize attribute value is used.\n"
3766"If size equals -1, all rows are fetched.\n";
3767
3768static PyObject *
3769sourceFetch(sourceObject *self, PyObject *args)
3770{
3771        PyObject   *reslist;
3772        int                     i,
3773                                k;
3774        long            size;
3775#if IS_PY3
3776        int                     encoding;
3777#endif
3778
3779        /* checks validity */
3780        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL | CHECK_CNX))
3781                return NULL;
3782
3783        /* checks args */
3784        size = self->arraysize;
3785        if (!PyArg_ParseTuple(args, "|l", &size))
3786        {
3787                PyErr_SetString(PyExc_TypeError,
3788                        "fetch(num), with num (integer, optional)");
3789                return NULL;
3790        }
3791
3792        /* seeks last line */
3793        /* limit size to be within the amount of data we actually have */
3794        if (size == -1 || (self->max_row - self->current_row) < size)
3795                size = self->max_row - self->current_row;
3796
3797        /* allocate list for result */
3798        if (!(reslist = PyList_New(0))) return NULL;
3799
3800#if IS_PY3
3801        encoding = self->encoding;
3802#endif
3803
3804        /* builds result */
3805        for (i = 0, k = self->current_row; i < size; ++i, ++k)
3806        {
3807                PyObject   *rowtuple;
3808                int                     j;
3809
3810                if (!(rowtuple = PyTuple_New(self->num_fields)))
3811                {
3812                        Py_DECREF(reslist); return NULL;
3813                }
3814
3815                for (j = 0; j < self->num_fields; ++j)
3816                {
3817                        PyObject   *str;
3818
3819                        if (PQgetisnull(self->result, k, j))
3820                        {
3821                                Py_INCREF(Py_None);
3822                                str = Py_None;
3823                        }
3824                        else
3825                        {
3826                                char *s = PQgetvalue(self->result, k, j);
3827                                Py_ssize_t size = PQgetlength(self->result, k, j);
3828#if IS_PY3
3829                                if (PQfformat(self->result, j) == 0) /* textual format */
3830                                {
3831                                        str = get_decoded_string(s, size, encoding);
3832                                        if (!str) /* cannot decode */
3833                                                str = PyBytes_FromStringAndSize(s, size);
3834                                }
3835                                else
3836#endif
3837                                str = PyBytes_FromStringAndSize(s, size);
3838                        }
3839                        PyTuple_SET_ITEM(rowtuple, j, str);
3840                }
3841
3842                if (PyList_Append(reslist, rowtuple))
3843                {
3844                        Py_DECREF(rowtuple); Py_DECREF(reslist); return NULL;
3845                }
3846                Py_DECREF(rowtuple);
3847        }
3848
3849        self->current_row = k;
3850        return reslist;
3851}
3852
3853/* changes current row (internal wrapper for all "move" methods) */
3854static PyObject *
3855pgsource_move(sourceObject *self, int move)
3856{
3857        /* checks validity */
3858        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
3859                return NULL;
3860
3861        /* changes the current row */
3862        switch (move)
3863        {
3864                case QUERY_MOVEFIRST:
3865                        self->current_row = 0;
3866                        break;
3867                case QUERY_MOVELAST:
3868                        self->current_row = self->max_row - 1;
3869                        break;
3870                case QUERY_MOVENEXT:
3871                        if (self->current_row != self->max_row)
3872                                ++self->current_row;
3873                        break;
3874                case QUERY_MOVEPREV:
3875                        if (self->current_row > 0)
3876                                self->current_row--;
3877                        break;
3878        }
3879
3880        Py_INCREF(Py_None);
3881        return Py_None;
3882}
3883
3884/* move to first result row */
3885static char sourceMoveFirst__doc__[] =
3886"movefirst() -- move to first result row";
3887
3888static PyObject *
3889sourceMoveFirst(sourceObject *self, PyObject *noargs)
3890{
3891        return pgsource_move(self, QUERY_MOVEFIRST);
3892}
3893
3894/* move to last result row */
3895static char sourceMoveLast__doc__[] =
3896"movelast() -- move to last valid result row";
3897
3898static PyObject *
3899sourceMoveLast(sourceObject *self, PyObject *noargs)
3900{
3901        return pgsource_move(self, QUERY_MOVELAST);
3902}
3903
3904/* move to next result row */
3905static char sourceMoveNext__doc__[] =
3906"movenext() -- move to next result row";
3907
3908static PyObject *
3909sourceMoveNext(sourceObject *self, PyObject *noargs)
3910{
3911        return pgsource_move(self, QUERY_MOVENEXT);
3912}
3913
3914/* move to previous result row */
3915static char sourceMovePrev__doc__[] =
3916"moveprev() -- move to previous result row";
3917
3918static PyObject *
3919sourceMovePrev(sourceObject *self, PyObject *noargs)
3920{
3921        return pgsource_move(self, QUERY_MOVEPREV);
3922}
3923
3924/* put copy data */
3925static char sourcePutData__doc__[] =
3926"putdata(buffer) -- send data to server during copy from stdin";
3927
3928static PyObject *
3929sourcePutData(sourceObject *self, PyObject *buffer)
3930{
3931        PyObject   *tmp_obj = NULL; /* an auxiliary object */
3932        char       *buf; /* the buffer as encoded string */
3933        Py_ssize_t      nbytes; /* length of string */
3934        char       *errormsg = NULL; /* error message */
3935        int                     res; /* direct result of the operation */
3936        PyObject   *ret; /* return value */
3937
3938        /* checks validity */
3939        if (!check_source_obj(self, CHECK_CNX))
3940                return NULL;
3941
3942        /* make sure that the connection object is valid */
3943        if (!self->pgcnx->cnx)
3944                return NULL;
3945
3946        if (buffer == Py_None)
3947        {
3948                /* pass None for terminating the operation */
3949                buf = errormsg = NULL;
3950        }
3951        else if (PyBytes_Check(buffer))
3952        {
3953                /* or pass a byte string */
3954                PyBytes_AsStringAndSize(buffer, &buf, &nbytes);
3955        }
3956        else if (PyUnicode_Check(buffer))
3957        {
3958                /* or pass a unicode string */
3959                tmp_obj = get_encoded_string(
3960                        buffer, PQclientEncoding(self->pgcnx->cnx));
3961                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
3962                PyBytes_AsStringAndSize(tmp_obj, &buf, &nbytes);
3963        }
3964        else if (PyErr_GivenExceptionMatches(buffer, PyExc_BaseException))
3965        {
3966                /* or pass a Python exception for sending an error message */
3967                tmp_obj = PyObject_Str(buffer);
3968                if (PyUnicode_Check(tmp_obj))
3969                {
3970                        PyObject *obj = tmp_obj;
3971                        tmp_obj = get_encoded_string(
3972                                obj, PQclientEncoding(self->pgcnx->cnx));
3973                        Py_DECREF(obj);
3974                        if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
3975                }
3976                errormsg = PyBytes_AsString(tmp_obj);
3977                buf = NULL;
3978        }
3979        else
3980        {
3981                PyErr_SetString(PyExc_TypeError,
3982                        "Method putdata() expects a buffer, None"
3983                         " or an exception as argument");
3984                return NULL;
3985        }
3986
3987        /* checks validity */
3988        if (!check_source_obj(self, CHECK_CNX | CHECK_RESULT) ||
3989                        PQresultStatus(self->result) != PGRES_COPY_IN)
3990        {
3991                PyErr_SetString(PyExc_IOError,
3992                        "Connection is invalid or not in copy_in state");
3993                Py_XDECREF(tmp_obj);
3994                return NULL;
3995        }
3996
3997        if (buf)
3998        {
3999                res = nbytes ? PQputCopyData(self->pgcnx->cnx, buf, (int)nbytes) : 1;
4000        }
4001        else
4002        {
4003                res = PQputCopyEnd(self->pgcnx->cnx, errormsg);
4004        }
4005
4006        Py_XDECREF(tmp_obj);
4007
4008        if (res != 1)
4009        {
4010                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->pgcnx->cnx));
4011                return NULL;
4012        }
4013
4014        if (buf) /* buffer has been sent */
4015        {
4016                ret = Py_None;
4017                Py_INCREF(ret);
4018        }
4019        else /* copy is done */
4020        {
4021                PGresult   *result; /* final result of the operation */
4022
4023                Py_BEGIN_ALLOW_THREADS;
4024                result = PQgetResult(self->pgcnx->cnx);
4025                Py_END_ALLOW_THREADS;
4026
4027                if (PQresultStatus(result) == PGRES_COMMAND_OK)
4028                {
4029                        char   *temp;
4030                        long    num_rows;
4031
4032                        temp = PQcmdTuples(result);
4033                        num_rows = temp[0] ? atol(temp) : -1;
4034                        ret = PyInt_FromLong(num_rows);
4035                }
4036                else
4037                {
4038                        if (!errormsg) errormsg = PQerrorMessage(self->pgcnx->cnx);
4039                        PyErr_SetString(PyExc_IOError, errormsg);
4040                        ret = NULL;
4041                }
4042
4043                PQclear(self->result);
4044                self->result = NULL;
4045                self->result_type = RESULT_EMPTY;
4046        }
4047
4048        return ret; /* None or number of rows */
4049}
4050
4051/* get copy data */
4052static char sourceGetData__doc__[] =
4053"getdata(decode) -- receive data to server during copy to stdout";
4054
4055static PyObject *
4056sourceGetData(sourceObject *self, PyObject *args)
4057{
4058        int                *decode = 0; /* decode flag */
4059        char       *buffer; /* the copied buffer as encoded byte string */
4060        Py_ssize_t      nbytes; /* length of the byte string */
4061        PyObject   *ret; /* return value */
4062
4063        /* checks validity */
4064        if (!check_source_obj(self, CHECK_CNX))
4065                return NULL;
4066
4067        /* make sure that the connection object is valid */
4068        if (!self->pgcnx->cnx)
4069                return NULL;
4070
4071        if (!PyArg_ParseTuple(args, "|i", &decode))
4072                return NULL;
4073
4074        /* checks validity */
4075        if (!check_source_obj(self, CHECK_CNX | CHECK_RESULT) ||
4076                        PQresultStatus(self->result) != PGRES_COPY_OUT)
4077        {
4078                PyErr_SetString(PyExc_IOError,
4079                        "Connection is invalid or not in copy_out state");
4080                return NULL;
4081        }
4082
4083        nbytes = PQgetCopyData(self->pgcnx->cnx, &buffer, 0);
4084
4085        if (!nbytes || nbytes < -1) /* an error occurred */
4086        {
4087                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->pgcnx->cnx));
4088                return NULL;
4089        }
4090
4091        if (nbytes == -1) /* copy is done */
4092        {
4093                PGresult   *result; /* final result of the operation */
4094
4095                Py_BEGIN_ALLOW_THREADS;
4096                result = PQgetResult(self->pgcnx->cnx);
4097                Py_END_ALLOW_THREADS;
4098
4099                if (PQresultStatus(result) == PGRES_COMMAND_OK)
4100                {
4101                        char   *temp;
4102                        long    num_rows;
4103
4104                        temp = PQcmdTuples(result);
4105                        num_rows = temp[0] ? atol(temp) : -1;
4106                        ret = PyInt_FromLong(num_rows);
4107                }
4108                else
4109                {
4110                        PyErr_SetString(PyExc_IOError, PQerrorMessage(self->pgcnx->cnx));
4111                        ret = NULL;
4112                }
4113
4114                PQclear(self->result);
4115                self->result = NULL;
4116                self->result_type = RESULT_EMPTY;
4117        }
4118        else /* a row has been returned */
4119        {
4120                ret = decode ? get_decoded_string(
4121                                buffer, nbytes, PQclientEncoding(self->pgcnx->cnx)) :
4122                        PyBytes_FromStringAndSize(buffer, nbytes);
4123                PQfreemem(buffer);
4124        }
4125
4126        return ret; /* buffer or number of rows */
4127}
4128
4129/* finds field number from string/integer (internal use only) */
4130static int
4131sourceFieldindex(sourceObject *self, PyObject *param, const char *usage)
4132{
4133        int                     num;
4134
4135        /* checks validity */
4136        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
4137                return -1;
4138
4139        /* gets field number */
4140        if (PyStr_Check(param))
4141                num = PQfnumber(self->result, PyBytes_AsString(param));
4142        else if (PyInt_Check(param))
4143                num = PyInt_AsLong(param);
4144        else
4145        {
4146                PyErr_SetString(PyExc_TypeError, usage);
4147                return -1;
4148        }
4149
4150        /* checks field validity */
4151        if (num < 0 || num >= self->num_fields)
4152        {
4153                PyErr_SetString(PyExc_ValueError, "Unknown field");
4154                return -1;
4155        }
4156
4157        return num;
4158}
4159
4160/* builds field information from position (internal use only) */
4161static PyObject *
4162pgsource_buildinfo(sourceObject *self, int num)
4163{
4164        PyObject *result;
4165
4166        /* allocates tuple */
4167        result = PyTuple_New(5);
4168        if (!result)
4169                return NULL;
4170
4171        /* affects field information */
4172        PyTuple_SET_ITEM(result, 0, PyInt_FromLong(num));
4173        PyTuple_SET_ITEM(result, 1,
4174                PyStr_FromString(PQfname(self->result, num)));
4175        PyTuple_SET_ITEM(result, 2,
4176                PyInt_FromLong(PQftype(self->result, num)));
4177        PyTuple_SET_ITEM(result, 3,
4178                PyInt_FromLong(PQfsize(self->result, num)));
4179        PyTuple_SET_ITEM(result, 4,
4180                PyInt_FromLong(PQfmod(self->result, num)));
4181
4182        return result;
4183}
4184
4185/* lists fields info */
4186static char sourceListInfo__doc__[] =
4187"listinfo() -- get information for all fields (position, name, type oid)";
4188
4189static PyObject *
4190sourceListInfo(sourceObject *self, PyObject *noargs)
4191{
4192        int                     i;
4193        PyObject   *result,
4194                           *info;
4195
4196        /* checks validity */
4197        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
4198                return NULL;
4199
4200        /* builds result */
4201        if (!(result = PyTuple_New(self->num_fields)))
4202                return NULL;
4203
4204        for (i = 0; i < self->num_fields; ++i)
4205        {
4206                info = pgsource_buildinfo(self, i);
4207                if (!info)
4208                {
4209                        Py_DECREF(result);
4210                        return NULL;
4211                }
4212                PyTuple_SET_ITEM(result, i, info);
4213        }
4214
4215        /* returns result */
4216        return result;
4217};
4218
4219/* list fields information for last result */
4220static char sourceFieldInfo__doc__[] =
4221"fieldinfo(desc) -- get specified field info (position, name, type oid)";
4222
4223static PyObject *
4224sourceFieldInfo(sourceObject *self, PyObject *desc)
4225{
4226        int                     num;
4227
4228        /* checks args and validity */
4229        if ((num = sourceFieldindex(self, desc,
4230                        "Method fieldinfo() needs a string or integer as argument")) == -1)
4231                return NULL;
4232
4233        /* returns result */
4234        return pgsource_buildinfo(self, num);
4235};
4236
4237/* retrieve field value */
4238static char sourceField__doc__[] =
4239"field(desc) -- return specified field value";
4240
4241static PyObject *
4242sourceField(sourceObject *self, PyObject *desc)
4243{
4244        int                     num;
4245
4246        /* checks args and validity */
4247        if ((num = sourceFieldindex(self, desc,
4248                        "Method field() needs a string or integer as argument")) == -1)
4249                return NULL;
4250
4251        return PyStr_FromString(
4252                PQgetvalue(self->result, self->current_row, num));
4253}
4254
4255/* get the list of source object attributes */
4256static PyObject *
4257sourceDir(connObject *self, PyObject *noargs)
4258{
4259        PyObject *attrs;
4260
4261        attrs = PyObject_Dir(PyObject_Type((PyObject *)self));
4262        PyObject_CallMethod(attrs, "extend", "[sssss]",
4263                "pgcnx", "arraysize", "resulttype", "ntuples", "nfields");
4264
4265        return attrs;
4266}
4267
4268/* source object methods */
4269static PyMethodDef sourceMethods[] = {
4270        {"__dir__", (PyCFunction) sourceDir,  METH_NOARGS, NULL},
4271        {"close", (PyCFunction) sourceClose, METH_NOARGS, sourceClose__doc__},
4272        {"execute", (PyCFunction) sourceExecute, METH_O, sourceExecute__doc__},
4273        {"oidstatus", (PyCFunction) sourceStatusOID, METH_NOARGS,
4274                        sourceStatusOID__doc__},
4275        {"fetch", (PyCFunction) sourceFetch, METH_VARARGS,
4276                        sourceFetch__doc__},
4277        {"movefirst", (PyCFunction) sourceMoveFirst, METH_NOARGS,
4278                        sourceMoveFirst__doc__},
4279        {"movelast", (PyCFunction) sourceMoveLast, METH_NOARGS,
4280                        sourceMoveLast__doc__},
4281        {"movenext", (PyCFunction) sourceMoveNext, METH_NOARGS,
4282                        sourceMoveNext__doc__},
4283        {"moveprev", (PyCFunction) sourceMovePrev, METH_NOARGS,
4284                        sourceMovePrev__doc__},
4285        {"putdata", (PyCFunction) sourcePutData, METH_O, sourcePutData__doc__},
4286        {"getdata", (PyCFunction) sourceGetData, METH_VARARGS,
4287                        sourceGetData__doc__},
4288        {"field", (PyCFunction) sourceField, METH_O,
4289                        sourceField__doc__},
4290        {"fieldinfo", (PyCFunction) sourceFieldInfo, METH_O,
4291                        sourceFieldInfo__doc__},
4292        {"listinfo", (PyCFunction) sourceListInfo, METH_NOARGS,
4293                        sourceListInfo__doc__},
4294        {NULL, NULL}
4295};
4296
4297/* gets source object attributes */
4298static PyObject *
4299sourceGetAttr(sourceObject *self, PyObject *nameobj)
4300{
4301        const char *name = PyStr_AsString(nameobj);
4302
4303        /* pg connection object */
4304        if (!strcmp(name, "pgcnx"))
4305        {
4306                if (check_source_obj(self, 0))
4307                {
4308                        Py_INCREF(self->pgcnx);
4309                        return (PyObject *) (self->pgcnx);
4310                }
4311                Py_INCREF(Py_None);
4312                return Py_None;
4313        }
4314
4315        /* arraysize */
4316        if (!strcmp(name, "arraysize"))
4317                return PyInt_FromLong(self->arraysize);
4318
4319        /* resulttype */
4320        if (!strcmp(name, "resulttype"))
4321                return PyInt_FromLong(self->result_type);
4322
4323        /* ntuples */
4324        if (!strcmp(name, "ntuples"))
4325                return PyInt_FromLong(self->max_row);
4326
4327        /* nfields */
4328        if (!strcmp(name, "nfields"))
4329                return PyInt_FromLong(self->num_fields);
4330
4331        /* seeks name in methods (fallback) */
4332        return PyObject_GenericGetAttr((PyObject *) self, nameobj);
4333}
4334
4335/* sets query object attributes */
4336static int
4337sourceSetAttr(sourceObject *self, char *name, PyObject *v)
4338{
4339        /* arraysize */
4340        if (!strcmp(name, "arraysize"))
4341        {
4342                if (!PyInt_Check(v))
4343                {
4344                        PyErr_SetString(PyExc_TypeError, "arraysize must be integer");
4345                        return -1;
4346                }
4347
4348                self->arraysize = PyInt_AsLong(v);
4349                return 0;
4350        }
4351
4352        /* unknown attribute */
4353        PyErr_SetString(PyExc_TypeError, "Not a writable attribute");
4354        return -1;
4355}
4356
4357/* return source object as string in human readable form */
4358static PyObject *
4359sourceStr(sourceObject *self)
4360{
4361        switch (self->result_type)
4362        {
4363                case RESULT_DQL:
4364                        return format_result(self->result);
4365                case RESULT_DDL:
4366                case RESULT_DML:
4367                        return PyStr_FromString(PQcmdStatus(self->result));
4368                case RESULT_EMPTY:
4369                default:
4370                        return PyStr_FromString("(empty PostgreSQL source object)");
4371        }
4372}
4373
4374static char source__doc__[] = "PyGreSQL source object";
4375
4376/* source type definition */
4377static PyTypeObject sourceType = {
4378        PyVarObject_HEAD_INIT(NULL, 0)
4379        "pgdb.Source",                                  /* tp_name */
4380        sizeof(sourceObject),                   /* tp_basicsize */
4381        0,                                                              /* tp_itemsize */
4382        /* methods */
4383        (destructor) sourceDealloc,             /* tp_dealloc */
4384        0,                                                              /* tp_print */
4385        0,                                                              /* tp_getattr */
4386        (setattrfunc) sourceSetAttr,    /* tp_setattr */
4387        0,                                                              /* tp_compare */
4388        0,                                                              /* tp_repr */
4389        0,                                                              /* tp_as_number */
4390        0,                                                              /* tp_as_sequence */
4391        0,                                                              /* tp_as_mapping */
4392        0,                                                              /* tp_hash */
4393        0,                                                              /* tp_call */
4394        (reprfunc) sourceStr,                   /* tp_str */
4395        (getattrofunc) sourceGetAttr,   /* tp_getattro */
4396        0,                                                              /* tp_setattro */
4397        0,                                                              /* tp_as_buffer */
4398        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
4399        source__doc__,                                  /* tp_doc */
4400        0,                                                              /* tp_traverse */
4401        0,                                                              /* tp_clear */
4402        0,                                                              /* tp_richcompare */
4403        0,                                                              /* tp_weaklistoffset */
4404        0,                                                              /* tp_iter */
4405        0,                                                              /* tp_iternext */
4406        sourceMethods,                                  /* tp_methods */
4407};
4408
4409/* connects to a database */
4410static char pgConnect__doc__[] =
4411"connect(dbname, host, port, opt) -- connect to a PostgreSQL database\n\n"
4412"The connection uses the specified parameters (optional, keywords aware).\n";
4413
4414static PyObject *
4415pgConnect(PyObject *self, PyObject *args, PyObject *dict)
4416{
4417        static const char *kwlist[] = {"dbname", "host", "port", "opt",
4418        "user", "passwd", NULL};
4419
4420        char       *pghost,
4421                           *pgopt,
4422                           *pgdbname,
4423                           *pguser,
4424                           *pgpasswd;
4425        int                     pgport;
4426        char            port_buffer[20];
4427        connObject *npgobj;
4428
4429        pghost = pgopt = pgdbname = pguser = pgpasswd = NULL;
4430        pgport = -1;
4431
4432        /*
4433         * parses standard arguments With the right compiler warnings, this
4434         * will issue a diagnostic. There is really no way around it.  If I
4435         * don't declare kwlist as const char *kwlist[] then it complains when
4436         * I try to assign all those constant strings to it.
4437         */
4438        if (!PyArg_ParseTupleAndKeywords(args, dict, "|zzizzz", (char **) kwlist,
4439                &pgdbname, &pghost, &pgport, &pgopt, &pguser, &pgpasswd))
4440                return NULL;
4441
4442#ifdef DEFAULT_VARS
4443        /* handles defaults variables (for uninitialised vars) */
4444        if ((!pghost) && (pg_default_host != Py_None))
4445                pghost = PyBytes_AsString(pg_default_host);
4446
4447        if ((pgport == -1) && (pg_default_port != Py_None))
4448                pgport = PyInt_AsLong(pg_default_port);
4449
4450        if ((!pgopt) && (pg_default_opt != Py_None))
4451                pgopt = PyBytes_AsString(pg_default_opt);
4452
4453        if ((!pgdbname) && (pg_default_base != Py_None))
4454                pgdbname = PyBytes_AsString(pg_default_base);
4455
4456        if ((!pguser) && (pg_default_user != Py_None))
4457                pguser = PyBytes_AsString(pg_default_user);
4458
4459        if ((!pgpasswd) && (pg_default_passwd != Py_None))
4460                pgpasswd = PyBytes_AsString(pg_default_passwd);
4461#endif /* DEFAULT_VARS */
4462
4463        if (!(npgobj = PyObject_NEW(connObject, &connType)))
4464        {
4465                set_error_msg(InternalError, "Can't create new connection object");
4466                return NULL;
4467        }
4468
4469        npgobj->valid = 1;
4470        npgobj->cnx = NULL;
4471        npgobj->date_format = date_format;
4472        npgobj->cast_hook = NULL;
4473        npgobj->notice_receiver = NULL;
4474
4475        if (pgport != -1)
4476        {
4477                memset(port_buffer, 0, sizeof(port_buffer));
4478                sprintf(port_buffer, "%d", pgport);
4479        }
4480
4481        Py_BEGIN_ALLOW_THREADS
4482        npgobj->cnx = PQsetdbLogin(pghost, pgport == -1 ? NULL : port_buffer,
4483                pgopt, NULL, pgdbname, pguser, pgpasswd);
4484        Py_END_ALLOW_THREADS
4485
4486        if (PQstatus(npgobj->cnx) == CONNECTION_BAD)
4487        {
4488                set_error(InternalError, "Cannot connect", npgobj->cnx, NULL);
4489                Py_XDECREF(npgobj);
4490                return NULL;
4491        }
4492
4493        return (PyObject *) npgobj;
4494}
4495
4496static void
4497queryDealloc(queryObject *self)
4498{
4499        Py_XDECREF(self->pgcnx);
4500        if (self->result)
4501                PQclear(self->result);
4502
4503        PyObject_Del(self);
4504}
4505
4506/* get number of rows */
4507static char queryNTuples__doc__[] =
4508"ntuples() -- return number of tuples returned by query";
4509
4510static PyObject *
4511queryNTuples(queryObject *self, PyObject *noargs)
4512{
4513        return PyInt_FromLong((long) PQntuples(self->result));
4514}
4515
4516/* list fields names from query result */
4517static char queryListFields__doc__[] =
4518"listfields() -- List field names from result";
4519
4520static PyObject *
4521queryListFields(queryObject *self, PyObject *noargs)
4522{
4523        int                     i,
4524                                n;
4525        char       *name;
4526        PyObject   *fieldstuple,
4527                           *str;
4528
4529        /* builds tuple */
4530        n = PQnfields(self->result);
4531        fieldstuple = PyTuple_New(n);
4532
4533        for (i = 0; i < n; ++i)
4534        {
4535                name = PQfname(self->result, i);
4536                str = PyStr_FromString(name);
4537                PyTuple_SET_ITEM(fieldstuple, i, str);
4538        }
4539
4540        return fieldstuple;
4541}
4542
4543/* get field name from last result */
4544static char queryFieldName__doc__[] =
4545"fieldname(num) -- return name of field from result from its position";
4546
4547static PyObject *
4548queryFieldName(queryObject *self, PyObject *args)
4549{
4550        int             i;
4551        char   *name;
4552
4553        /* gets args */
4554        if (!PyArg_ParseTuple(args, "i", &i))
4555        {
4556                PyErr_SetString(PyExc_TypeError,
4557                        "Method fieldname() takes an integer as argument");
4558                return NULL;
4559        }
4560
4561        /* checks number validity */
4562        if (i >= PQnfields(self->result))
4563        {
4564                PyErr_SetString(PyExc_ValueError, "Invalid field number");
4565                return NULL;
4566        }
4567
4568        /* gets fields name and builds object */
4569        name = PQfname(self->result, i);
4570        return PyStr_FromString(name);
4571}
4572
4573/* gets fields number from name in last result */
4574static char queryFieldNumber__doc__[] =
4575"fieldnum(name) -- return position in query for field from its name";
4576
4577static PyObject *
4578queryFieldNumber(queryObject *self, PyObject *args)
4579{
4580        int             num;
4581        char   *name;
4582
4583        /* gets args */
4584        if (!PyArg_ParseTuple(args, "s", &name))
4585        {
4586                PyErr_SetString(PyExc_TypeError,
4587                        "Method fieldnum() takes a string as argument");
4588                return NULL;
4589        }
4590
4591        /* gets field number */
4592        if ((num = PQfnumber(self->result, name)) == -1)
4593        {
4594                PyErr_SetString(PyExc_ValueError, "Unknown field");
4595                return NULL;
4596        }
4597
4598        return PyInt_FromLong(num);
4599}
4600
4601/* retrieves last result */
4602static char queryGetResult__doc__[] =
4603"getresult() -- Get the result of a query\n\n"
4604"The result is returned as a list of rows, each one a tuple of fields\n"
4605"in the order returned by the server.\n";
4606
4607static PyObject *
4608queryGetResult(queryObject *self, PyObject *noargs)
4609{
4610        PyObject   *reslist;
4611        int                     i, m, n, *col_types;
4612        int                     encoding = self->encoding;
4613
4614        /* stores result in tuple */
4615        m = PQntuples(self->result);
4616        n = PQnfields(self->result);
4617        if (!(reslist = PyList_New(m))) return NULL;
4618
4619        if (!(col_types = get_col_types(self->result, n))) return NULL;
4620
4621        for (i = 0; i < m; ++i)
4622        {
4623                PyObject   *rowtuple;
4624                int                     j;
4625
4626                if (!(rowtuple = PyTuple_New(n)))
4627                {
4628                        Py_DECREF(reslist);
4629                        reslist = NULL;
4630                        goto exit;
4631                }
4632
4633                for (j = 0; j < n; ++j)
4634                {
4635                        PyObject * val;
4636
4637                        if (PQgetisnull(self->result, i, j))
4638                        {
4639                                Py_INCREF(Py_None);
4640                                val = Py_None;
4641                        }
4642                        else /* not null */
4643                        {
4644                                /* get the string representation of the value */
4645                                /* note: this is always null-terminated text format */
4646                                char   *s = PQgetvalue(self->result, i, j);
4647                                /* get the PyGreSQL type of the column */
4648                                int             type = col_types[j];
4649
4650                                if (type & PYGRES_ARRAY)
4651                                        val = cast_array(s, PQgetlength(self->result, i, j),
4652                                                encoding, type, NULL, 0);
4653                                else if (type == PYGRES_BYTEA)
4654                                        val = cast_bytea_text(s);
4655                                else if (type == PYGRES_OTHER)
4656                                        val = cast_other(s,
4657                                                PQgetlength(self->result, i, j), encoding,
4658                                                PQftype(self->result, j), self->pgcnx->cast_hook);
4659                                else if (type & PYGRES_TEXT)
4660                                        val = cast_sized_text(s, PQgetlength(self->result, i, j),
4661                                                encoding, type);
4662                                else
4663                                        val = cast_unsized_simple(s, type);
4664                        }
4665
4666                        if (!val)
4667                        {
4668                                Py_DECREF(reslist);
4669                                Py_DECREF(rowtuple);
4670                                reslist = NULL;
4671                                goto exit;
4672                        }
4673
4674                        PyTuple_SET_ITEM(rowtuple, j, val);
4675                }
4676
4677                PyList_SET_ITEM(reslist, i, rowtuple);
4678        }
4679
4680exit:
4681        PyMem_Free(col_types);
4682
4683        /* returns list */
4684        return reslist;
4685}
4686
4687/* retrieves last result as a list of dictionaries*/
4688static char queryDictResult__doc__[] =
4689"dictresult() -- Get the result of a query\n\n"
4690"The result is returned as a list of rows, each one a dictionary with\n"
4691"the field names used as the labels.\n";
4692
4693static PyObject *
4694queryDictResult(queryObject *self, PyObject *noargs)
4695{
4696        PyObject   *reslist;
4697        int                     i,
4698                                m,
4699                                n,
4700                           *col_types;
4701        int                     encoding = self->encoding;
4702
4703        /* stores result in list */
4704        m = PQntuples(self->result);
4705        n = PQnfields(self->result);
4706        if (!(reslist = PyList_New(m))) return NULL;
4707
4708        if (!(col_types = get_col_types(self->result, n))) return NULL;
4709
4710        for (i = 0; i < m; ++i)
4711        {
4712                PyObject   *dict;
4713                int                     j;
4714
4715                if (!(dict = PyDict_New()))
4716                {
4717                        Py_DECREF(reslist);
4718                        reslist = NULL;
4719                        goto exit;
4720                }
4721
4722                for (j = 0; j < n; ++j)
4723                {
4724                        PyObject * val;
4725
4726                        if (PQgetisnull(self->result, i, j))
4727                        {
4728                                Py_INCREF(Py_None);
4729                                val = Py_None;
4730                        }
4731                        else /* not null */
4732                        {
4733                                /* get the string representation of the value */
4734                                /* note: this is always null-terminated text format */
4735                                char   *s = PQgetvalue(self->result, i, j);
4736                                /* get the PyGreSQL type of the column */
4737                                int             type = col_types[j];
4738
4739                                if (type & PYGRES_ARRAY)
4740                                        val = cast_array(s, PQgetlength(self->result, i, j),
4741                                                encoding, type, NULL, 0);
4742                                else if (type == PYGRES_BYTEA)
4743                                        val = cast_bytea_text(s);
4744                                else if (type == PYGRES_OTHER)
4745                                        val = cast_other(s,
4746                                                PQgetlength(self->result, i, j), encoding,
4747                                                PQftype(self->result, j), self->pgcnx->cast_hook);
4748                                else if (type & PYGRES_TEXT)
4749                                        val = cast_sized_text(s, PQgetlength(self->result, i, j),
4750                                                encoding, type);
4751                                else
4752                                        val = cast_unsized_simple(s, type);
4753                        }
4754
4755                        if (!val)
4756                        {
4757                                Py_DECREF(dict);
4758                                Py_DECREF(reslist);
4759                                reslist = NULL;
4760                                goto exit;
4761                        }
4762
4763                        PyDict_SetItemString(dict, PQfname(self->result, j), val);
4764                        Py_DECREF(val);
4765                }
4766
4767                PyList_SET_ITEM(reslist, i, dict);
4768        }
4769
4770exit:
4771        PyMem_Free(col_types);
4772
4773        /* returns list */
4774        return reslist;
4775}
4776
4777/* retrieves last result as named tuples */
4778static char queryNamedResult__doc__[] =
4779"namedresult() -- Get the result of a query\n\n"
4780"The result is returned as a list of rows, each one a tuple of fields\n"
4781"in the order returned by the server.\n";
4782
4783static PyObject *
4784queryNamedResult(queryObject *self, PyObject *noargs)
4785{
4786        PyObject   *ret;
4787
4788        if (namedresult)
4789        {
4790                ret = PyObject_CallFunction(namedresult, "(O)", self);
4791
4792                if (ret == NULL)
4793                        return NULL;
4794                }
4795        else
4796        {
4797                ret = queryGetResult(self, NULL);
4798        }
4799
4800        return ret;
4801}
4802
4803/* gets notice object attributes */
4804static PyObject *
4805noticeGetAttr(noticeObject *self, PyObject *nameobj)
4806{
4807        PGresult const *res = self->res;
4808        const char *name = PyStr_AsString(nameobj);
4809        int fieldcode;
4810
4811        if (!res)
4812        {
4813                PyErr_SetString(PyExc_TypeError, "Cannot get current notice");
4814                return NULL;
4815        }
4816
4817        /* pg connection object */
4818        if (!strcmp(name, "pgcnx"))
4819        {
4820                if (self->pgcnx && check_cnx_obj(self->pgcnx))
4821                {
4822                        Py_INCREF(self->pgcnx);
4823                        return (PyObject *) self->pgcnx;
4824                }
4825                else
4826                {
4827                        Py_INCREF(Py_None);
4828                        return Py_None;
4829                }
4830        }
4831
4832        /* full message */
4833        if (!strcmp(name, "message"))
4834                return PyStr_FromString(PQresultErrorMessage(res));
4835
4836        /* other possible fields */
4837        fieldcode = 0;
4838        if (!strcmp(name, "severity"))
4839                fieldcode = PG_DIAG_SEVERITY;
4840        else if (!strcmp(name, "primary"))
4841                fieldcode = PG_DIAG_MESSAGE_PRIMARY;
4842        else if (!strcmp(name, "detail"))
4843                fieldcode = PG_DIAG_MESSAGE_DETAIL;
4844        else if (!strcmp(name, "hint"))
4845                fieldcode = PG_DIAG_MESSAGE_HINT;
4846        if (fieldcode)
4847        {
4848                char *s = PQresultErrorField(res, fieldcode);
4849                if (s)
4850                        return PyStr_FromString(s);
4851                else
4852                {
4853                        Py_INCREF(Py_None); return Py_None;
4854                }
4855        }
4856
4857        return PyObject_GenericGetAttr((PyObject *) self, nameobj);
4858}
4859
4860/* return notice as string in human readable form */
4861static PyObject *
4862noticeStr(noticeObject *self)
4863{
4864        return noticeGetAttr(self, PyBytes_FromString("message"));
4865}
4866
4867/* get the list of notice attributes */
4868static PyObject *
4869noticeDir(noticeObject *self, PyObject *noargs)
4870{
4871        PyObject *attrs;
4872
4873        attrs = PyObject_Dir(PyObject_Type((PyObject *)self));
4874        PyObject_CallMethod(attrs, "extend", "[ssssss]",
4875                "pgcnx", "severity", "message", "primary", "detail", "hint");
4876
4877        return attrs;
4878}
4879
4880/* notice object methods */
4881static struct PyMethodDef noticeMethods[] = {
4882        {"__dir__", (PyCFunction) noticeDir,  METH_NOARGS, NULL},
4883        {NULL, NULL}
4884};
4885
4886/* notice type definition */
4887static PyTypeObject noticeType = {
4888        PyVarObject_HEAD_INIT(NULL, 0)
4889        "pg.Notice",                                    /* tp_name */
4890        sizeof(noticeObject),                   /* tp_basicsize */
4891        0,                                                              /* tp_itemsize */
4892        /* methods */
4893        0,                                                              /* tp_dealloc */
4894        0,                                                              /* tp_print */
4895        0,                                                              /* tp_getattr */
4896        0,                                                              /* tp_setattr */
4897        0,                                                              /* tp_compare */
4898        0,                                                              /* tp_repr */
4899        0,                                                              /* tp_as_number */
4900        0,                                                              /* tp_as_sequence */
4901        0,                                                              /* tp_as_mapping */
4902        0,                                                              /* tp_hash */
4903        0,                                                              /* tp_call */
4904        (reprfunc) noticeStr,                   /* tp_str */
4905        (getattrofunc) noticeGetAttr,   /* tp_getattro */
4906        PyObject_GenericSetAttr,                /* tp_setattro */
4907        0,                                                              /* tp_as_buffer */
4908        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
4909        0,                                                              /* tp_doc */
4910        0,                                                              /* tp_traverse */
4911        0,                                                              /* tp_clear */
4912        0,                                                              /* tp_richcompare */
4913        0,                                                              /* tp_weaklistoffset */
4914        0,                                                              /* tp_iter */
4915        0,                                                              /* tp_iternext */
4916        noticeMethods,                                  /* tp_methods */
4917};
4918
4919/* query object methods */
4920static struct PyMethodDef queryMethods[] = {
4921        {"getresult", (PyCFunction) queryGetResult, METH_NOARGS,
4922                        queryGetResult__doc__},
4923        {"dictresult", (PyCFunction) queryDictResult, METH_NOARGS,
4924                        queryDictResult__doc__},
4925        {"namedresult", (PyCFunction) queryNamedResult, METH_NOARGS,
4926                        queryNamedResult__doc__},
4927        {"fieldname", (PyCFunction) queryFieldName, METH_VARARGS,
4928                         queryFieldName__doc__},
4929        {"fieldnum", (PyCFunction) queryFieldNumber, METH_VARARGS,
4930                        queryFieldNumber__doc__},
4931        {"listfields", (PyCFunction) queryListFields, METH_NOARGS,
4932                        queryListFields__doc__},
4933        {"ntuples", (PyCFunction) queryNTuples, METH_NOARGS,
4934                        queryNTuples__doc__},
4935        {NULL, NULL}
4936};
4937
4938/* query type definition */
4939static PyTypeObject queryType = {
4940        PyVarObject_HEAD_INIT(NULL, 0)
4941        "pg.Query",                                             /* tp_name */
4942        sizeof(queryObject),                    /* tp_basicsize */
4943        0,                                                              /* tp_itemsize */
4944        /* methods */
4945        (destructor) queryDealloc,              /* tp_dealloc */
4946        0,                                                              /* tp_print */
4947        0,                                                              /* tp_getattr */
4948        0,                                                              /* tp_setattr */
4949        0,                                                              /* tp_compare */
4950        0,                                                              /* tp_repr */
4951        0,                                                              /* tp_as_number */
4952        0,                                                              /* tp_as_sequence */
4953        0,                                                              /* tp_as_mapping */
4954        0,                                                              /* tp_hash */
4955        0,                                                              /* tp_call */
4956        (reprfunc) queryStr,                    /* tp_str */
4957        PyObject_GenericGetAttr,                /* tp_getattro */
4958        0,                                                              /* tp_setattro */
4959        0,                                                              /* tp_as_buffer */
4960        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
4961        0,                                                              /* tp_doc */
4962        0,                                                              /* tp_traverse */
4963        0,                                                              /* tp_clear */
4964        0,                                                              /* tp_richcompare */
4965        0,                                                              /* tp_weaklistoffset */
4966        0,                                                              /* tp_iter */
4967        0,                                                              /* tp_iternext */
4968        queryMethods,                                   /* tp_methods */
4969};
4970
4971/* --------------------------------------------------------------------- */
4972
4973/* MODULE FUNCTIONS */
4974
4975/* escape string */
4976static char pgEscapeString__doc__[] =
4977"escape_string(string) -- escape a string for use within SQL";
4978
4979static PyObject *
4980pgEscapeString(PyObject *self, PyObject *string)
4981{
4982        PyObject   *tmp_obj = NULL, /* auxiliary string object */
4983                           *to_obj; /* string object to return */
4984        char       *from, /* our string argument as encoded string */
4985                           *to; /* the result as encoded string */
4986        Py_ssize_t      from_length; /* length of string */
4987        size_t          to_length; /* length of result */
4988        int                     encoding = -1; /* client encoding */
4989
4990        if (PyBytes_Check(string))
4991        {
4992                PyBytes_AsStringAndSize(string, &from, &from_length);
4993        }
4994        else if (PyUnicode_Check(string))
4995        {
4996                encoding = pg_encoding_ascii;
4997                tmp_obj = get_encoded_string(string, encoding);
4998                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
4999                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
5000        }
5001        else
5002        {
5003                PyErr_SetString(PyExc_TypeError,
5004                        "Method escape_string() expects a string as argument");
5005                return NULL;
5006        }
5007
5008        to_length = 2*from_length + 1;
5009        if ((Py_ssize_t)to_length < from_length) /* overflow */
5010        {
5011                to_length = from_length;
5012                from_length = (from_length - 1)/2;
5013        }
5014        to = (char *)PyMem_Malloc(to_length);
5015        to_length = (int)PQescapeString(to, from, (size_t)from_length);
5016
5017        Py_XDECREF(tmp_obj);
5018
5019        if (encoding == -1)
5020                to_obj = PyBytes_FromStringAndSize(to, to_length);
5021        else
5022                to_obj = get_decoded_string(to, to_length, encoding);
5023        PyMem_Free(to);
5024        return to_obj;
5025}
5026
5027/* escape bytea */
5028static char pgEscapeBytea__doc__[] =
5029"escape_bytea(data) -- escape binary data for use within SQL as type bytea";
5030
5031static PyObject *
5032pgEscapeBytea(PyObject *self, PyObject *data)
5033{
5034        PyObject   *tmp_obj = NULL, /* auxiliary string object */
5035                           *to_obj; /* string object to return */
5036        char       *from, /* our string argument as encoded string */
5037                           *to; /* the result as encoded string */
5038        Py_ssize_t      from_length; /* length of string */
5039        size_t          to_length; /* length of result */
5040        int                     encoding = -1; /* client encoding */
5041
5042        if (PyBytes_Check(data))
5043        {
5044                PyBytes_AsStringAndSize(data, &from, &from_length);
5045        }
5046        else if (PyUnicode_Check(data))
5047        {
5048                encoding = pg_encoding_ascii;
5049                tmp_obj = get_encoded_string(data, encoding);
5050                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
5051                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
5052        }
5053        else
5054        {
5055                PyErr_SetString(PyExc_TypeError,
5056                        "Method escape_bytea() expects a string as argument");
5057                return NULL;
5058        }
5059
5060        to = (char *)PQescapeBytea(
5061                (unsigned char*)from, (size_t)from_length, &to_length);
5062
5063        Py_XDECREF(tmp_obj);
5064
5065        if (encoding == -1)
5066                to_obj = PyBytes_FromStringAndSize(to, to_length - 1);
5067        else
5068                to_obj = get_decoded_string(to, to_length - 1, encoding);
5069        if (to)
5070                PQfreemem(to);
5071        return to_obj;
5072}
5073
5074/* unescape bytea */
5075static char pgUnescapeBytea__doc__[] =
5076"unescape_bytea(string) -- unescape bytea data retrieved as text";
5077
5078static PyObject *
5079pgUnescapeBytea(PyObject *self, PyObject *data)
5080{
5081        PyObject   *tmp_obj = NULL, /* auxiliary string object */
5082                           *to_obj; /* string object to return */
5083        char       *from, /* our string argument as encoded string */
5084                           *to; /* the result as encoded string */
5085        Py_ssize_t      from_length; /* length of string */
5086        size_t          to_length; /* length of result */
5087
5088        if (PyBytes_Check(data))
5089        {
5090                PyBytes_AsStringAndSize(data, &from, &from_length);
5091        }
5092        else if (PyUnicode_Check(data))
5093        {
5094                tmp_obj = get_encoded_string(data, pg_encoding_ascii);
5095                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
5096                PyBytes_AsStringAndSize(tmp_obj, &from, &from_length);
5097        }
5098        else
5099        {
5100                PyErr_SetString(PyExc_TypeError,
5101                        "Method unescape_bytea() expects a string as argument");
5102                return NULL;
5103        }
5104
5105        to = (char *)PQunescapeBytea((unsigned char*)from, &to_length);
5106
5107        Py_XDECREF(tmp_obj);
5108
5109        if (!to) return PyErr_NoMemory();
5110
5111        to_obj = PyBytes_FromStringAndSize(to, to_length);
5112        PQfreemem(to);
5113
5114        return to_obj;
5115}
5116
5117/* set fixed datestyle */
5118static char pgSetDatestyle__doc__[] =
5119"set_datestyle(style) -- set which style is assumed";
5120
5121static PyObject *
5122pgSetDatestyle(PyObject *self, PyObject *args)
5123{
5124        const char         *datestyle = NULL;
5125
5126        /* gets arguments */
5127        if (!PyArg_ParseTuple(args, "z", &datestyle))
5128        {
5129                PyErr_SetString(PyExc_TypeError,
5130                        "Function set_datestyle() expects a string or None as argument");
5131                return NULL;
5132        }
5133
5134        date_format = datestyle ? date_style_to_format(datestyle) : NULL;
5135
5136        Py_INCREF(Py_None); return Py_None;
5137}
5138
5139/* get fixed datestyle */
5140static char pgGetDatestyle__doc__[] =
5141"get_datestyle() -- get which date style is assumed";
5142
5143static PyObject *
5144pgGetDatestyle(PyObject *self, PyObject *noargs)
5145{
5146        if (date_format)
5147        {
5148                return PyStr_FromString(date_format_to_style(date_format));
5149        }
5150        else
5151        {
5152                Py_INCREF(Py_None); return Py_None;
5153        }
5154}
5155
5156/* get decimal point */
5157static char pgGetDecimalPoint__doc__[] =
5158"get_decimal_point() -- get decimal point to be used for money values";
5159
5160static PyObject *
5161pgGetDecimalPoint(PyObject *self, PyObject *noargs)
5162{
5163        PyObject *ret;
5164        char s[2];
5165
5166        if (decimal_point)
5167        {
5168                s[0] = decimal_point; s[1] = '\0';
5169                ret = PyStr_FromString(s);
5170        }
5171        else
5172        {
5173                Py_INCREF(Py_None); ret = Py_None;
5174        }
5175
5176        return ret;
5177}
5178
5179/* set decimal point */
5180static char pgSetDecimalPoint__doc__[] =
5181"set_decimal_point(char) -- set decimal point to be used for money values";
5182
5183static PyObject *
5184pgSetDecimalPoint(PyObject *self, PyObject *args)
5185{
5186        PyObject *ret = NULL;
5187        char *s = NULL;
5188
5189        /* gets arguments */
5190        if (PyArg_ParseTuple(args, "z", &s))
5191        {
5192                if (!s)
5193                        s = "\0";
5194                else if (*s && (*(s+1) || !strchr(".,;: '*/_`|", *s)))
5195                        s = NULL;
5196        }
5197
5198        if (s)
5199        {
5200                decimal_point = *s;
5201                Py_INCREF(Py_None); ret = Py_None;
5202        }
5203        else
5204                PyErr_SetString(PyExc_TypeError,
5205                        "Function set_decimal_mark() expects"
5206                        " a decimal mark character as argument");
5207
5208        return ret;
5209}
5210
5211/* get decimal type */
5212static char pgGetDecimal__doc__[] =
5213"get_decimal() -- get the decimal type to be used for numeric values";
5214
5215static PyObject *
5216pgGetDecimal(PyObject *self, PyObject *noargs)
5217{
5218        PyObject *ret;
5219
5220        ret = decimal ? decimal : Py_None;
5221        Py_INCREF(ret);
5222
5223        return ret;
5224}
5225
5226/* set decimal type */
5227static char pgSetDecimal__doc__[] =
5228"set_decimal(cls) -- set a decimal type to be used for numeric values";
5229
5230static PyObject *
5231pgSetDecimal(PyObject *self, PyObject *cls)
5232{
5233        PyObject *ret = NULL;
5234
5235        if (cls == Py_None)
5236        {
5237                Py_XDECREF(decimal); decimal = NULL;
5238                Py_INCREF(Py_None); ret = Py_None;
5239        }
5240        else if (PyCallable_Check(cls))
5241        {
5242                Py_XINCREF(cls); Py_XDECREF(decimal); decimal = cls;
5243                Py_INCREF(Py_None); ret = Py_None;
5244        }
5245        else
5246                PyErr_SetString(PyExc_TypeError,
5247                        "Function set_decimal() expects"
5248                         " a callable or None as argument");
5249
5250        return ret;
5251}
5252
5253/* get usage of bool values */
5254static char pgGetBool__doc__[] =
5255"get_bool() -- check whether boolean values are converted to bool";
5256
5257static PyObject *
5258pgGetBool(PyObject *self, PyObject *noargs)
5259{
5260        PyObject *ret;
5261
5262        ret = bool_as_text ? Py_False : Py_True;
5263        Py_INCREF(ret);
5264
5265        return ret;
5266}
5267
5268/* set usage of bool values */
5269static char pgSetBool__doc__[] =
5270"set_bool(on) -- set whether boolean values should be converted to bool";
5271
5272static PyObject *
5273pgSetBool(PyObject *self, PyObject *args)
5274{
5275        PyObject *ret = NULL;
5276        int                     i;
5277
5278        /* gets arguments */
5279        if (PyArg_ParseTuple(args, "i", &i))
5280        {
5281                bool_as_text = i ? 0 : 1;
5282                Py_INCREF(Py_None); ret = Py_None;
5283        }
5284        else
5285                PyErr_SetString(PyExc_TypeError,
5286                        "Function set_bool() expects a boolean value as argument");
5287
5288        return ret;
5289}
5290
5291/* get conversion of arrays to lists */
5292static char pgGetArray__doc__[] =
5293"get_array() -- check whether arrays are converted as lists";
5294
5295static PyObject *
5296pgGetArray(PyObject *self, PyObject *noargs)
5297{
5298        PyObject *ret;
5299
5300        ret = array_as_text ? Py_False : Py_True;
5301        Py_INCREF(ret);
5302
5303        return ret;
5304}
5305
5306/* set conversion of arrays to lists */
5307static char pgSetArray__doc__[] =
5308"set_array(on) -- set whether arrays should be converted to lists";
5309
5310static PyObject *
5311pgSetArray(PyObject *self, PyObject *args)
5312{
5313        PyObject *ret = NULL;
5314        int                     i;
5315
5316        /* gets arguments */
5317        if (PyArg_ParseTuple(args, "i", &i))
5318        {
5319                array_as_text = i ? 0 : 1;
5320                Py_INCREF(Py_None); ret = Py_None;
5321        }
5322        else
5323                PyErr_SetString(PyExc_TypeError,
5324                        "Function set_array() expects a boolean value as argument");
5325
5326        return ret;
5327}
5328
5329/* check whether bytea values are unescaped */
5330static char pgGetByteaEscaped__doc__[] =
5331"get_bytea_escaped() -- check whether bytea will be returned escaped";
5332
5333static PyObject *
5334pgGetByteaEscaped(PyObject *self, PyObject *noargs)
5335{
5336        PyObject *ret;
5337
5338        ret = bytea_escaped ? Py_True : Py_False;
5339        Py_INCREF(ret);
5340
5341        return ret;
5342}
5343
5344/* set usage of bool values */
5345static char pgSetByteaEscaped__doc__[] =
5346"set_bytea_escaped(on) -- set whether bytea will be returned escaped";
5347
5348static PyObject *
5349pgSetByteaEscaped(PyObject *self, PyObject *args)
5350{
5351        PyObject *ret = NULL;
5352        int                     i;
5353
5354        /* gets arguments */
5355        if (PyArg_ParseTuple(args, "i", &i))
5356        {
5357                bytea_escaped = i ? 1 : 0;
5358                Py_INCREF(Py_None); ret = Py_None;
5359        }
5360        else
5361                PyErr_SetString(PyExc_TypeError,
5362                        "Function set_bytea_escaped() expects a boolean value as argument");
5363
5364        return ret;
5365}
5366
5367/* get named result factory */
5368static char pgGetNamedresult__doc__[] =
5369"get_namedresult() -- get the function used for getting named results";
5370
5371static PyObject *
5372pgGetNamedresult(PyObject *self, PyObject *noargs)
5373{
5374        PyObject *ret;
5375
5376        ret = namedresult ? namedresult : Py_None;
5377        Py_INCREF(ret);
5378
5379        return ret;
5380}
5381
5382/* set named result factory */
5383static char pgSetNamedresult__doc__[] =
5384"set_namedresult(func) -- set a function to be used for getting named results";
5385
5386static PyObject *
5387pgSetNamedresult(PyObject *self, PyObject *func)
5388{
5389        PyObject *ret = NULL;
5390
5391        if (func == Py_None)
5392        {
5393                Py_XDECREF(namedresult); namedresult = NULL;
5394                Py_INCREF(Py_None); ret = Py_None;
5395        }
5396        else if (PyCallable_Check(func))
5397        {
5398                Py_XINCREF(func); Py_XDECREF(namedresult); namedresult = func;
5399                Py_INCREF(Py_None); ret = Py_None;
5400        }
5401        else
5402                PyErr_SetString(PyExc_TypeError,
5403                        "Function set_namedresult() expects"
5404                         " a callable or None as argument");
5405
5406        return ret;
5407}
5408
5409/* get json decode function */
5410static char pgGetJsondecode__doc__[] =
5411"get_jsondecode() -- get the function used for decoding json results";
5412
5413static PyObject *
5414pgGetJsondecode(PyObject *self, PyObject *noargs)
5415{
5416        PyObject *ret;
5417
5418        ret = jsondecode;
5419        if (!ret)
5420                ret = Py_None;
5421        Py_INCREF(ret);
5422
5423        return ret;
5424}
5425
5426/* set json decode function */
5427static char pgSetJsondecode__doc__[] =
5428"set_jsondecode(func) -- set a function to be used for decoding json results";
5429
5430static PyObject *
5431pgSetJsondecode(PyObject *self, PyObject *func)
5432{
5433        PyObject *ret = NULL;
5434
5435        if (func == Py_None)
5436        {
5437                Py_XDECREF(jsondecode); jsondecode = NULL;
5438                Py_INCREF(Py_None); ret = Py_None;
5439        }
5440        else if (PyCallable_Check(func))
5441        {
5442                Py_XINCREF(func); Py_XDECREF(jsondecode); jsondecode = func;
5443                Py_INCREF(Py_None); ret = Py_None;
5444        }
5445        else
5446                PyErr_SetString(PyExc_TypeError,
5447                        "Function jsondecode() expects"
5448                         " a callable or None as argument");
5449
5450        return ret;
5451}
5452
5453#ifdef DEFAULT_VARS
5454
5455/* gets default host */
5456static char pgGetDefHost__doc__[] =
5457"get_defhost() -- return default database host";
5458
5459static PyObject *
5460pgGetDefHost(PyObject *self, PyObject *noargs)
5461{
5462        Py_XINCREF(pg_default_host);
5463        return pg_default_host;
5464}
5465
5466/* sets default host */
5467static char pgSetDefHost__doc__[] =
5468"set_defhost(string) -- set default database host and return previous value";
5469
5470static PyObject *
5471pgSetDefHost(PyObject *self, PyObject *args)
5472{
5473        char       *temp = NULL;
5474        PyObject   *old;
5475
5476        /* gets arguments */
5477        if (!PyArg_ParseTuple(args, "z", &temp))
5478        {
5479                PyErr_SetString(PyExc_TypeError,
5480                        "Function set_defhost() expects a string or None as argument");
5481                return NULL;
5482        }
5483
5484        /* adjusts value */
5485        old = pg_default_host;
5486
5487        if (temp)
5488                pg_default_host = PyStr_FromString(temp);
5489        else
5490        {
5491                Py_INCREF(Py_None);
5492                pg_default_host = Py_None;
5493        }
5494
5495        return old;
5496}
5497
5498/* gets default base */
5499static char pgGetDefBase__doc__[] =
5500"get_defbase() -- return default database name";
5501
5502static PyObject *
5503pgGetDefBase(PyObject *self, PyObject *noargs)
5504{
5505        Py_XINCREF(pg_default_base);
5506        return pg_default_base;
5507}
5508
5509/* sets default base */
5510static char pgSetDefBase__doc__[] =
5511"set_defbase(string) -- set default database name and return previous value";
5512
5513static PyObject *
5514pgSetDefBase(PyObject *self, PyObject *args)
5515{
5516        char       *temp = NULL;
5517        PyObject   *old;
5518
5519        /* gets arguments */
5520        if (!PyArg_ParseTuple(args, "z", &temp))
5521        {
5522                PyErr_SetString(PyExc_TypeError,
5523                        "Function set_defbase() Argument a string or None as argument");
5524                return NULL;
5525        }
5526
5527        /* adjusts value */
5528        old = pg_default_base;
5529
5530        if (temp)
5531                pg_default_base = PyStr_FromString(temp);
5532        else
5533        {
5534                Py_INCREF(Py_None);
5535                pg_default_base = Py_None;
5536        }
5537
5538        return old;
5539}
5540
5541/* gets default options */
5542static char pgGetDefOpt__doc__[] =
5543"get_defopt() -- return default database options";
5544
5545static PyObject *
5546pgGetDefOpt(PyObject *self, PyObject *noargs)
5547{
5548        Py_XINCREF(pg_default_opt);
5549        return pg_default_opt;
5550}
5551
5552/* sets default opt */
5553static char pgSetDefOpt__doc__[] =
5554"set_defopt(string) -- set default options and return previous value";
5555
5556static PyObject *
5557pgSetDefOpt(PyObject *self, PyObject *args)
5558{
5559        char       *temp = NULL;
5560        PyObject   *old;
5561
5562        /* gets arguments */
5563        if (!PyArg_ParseTuple(args, "z", &temp))
5564        {
5565                PyErr_SetString(PyExc_TypeError,
5566                        "Function set_defopt() expects a string or None as argument");
5567                return NULL;
5568        }
5569
5570        /* adjusts value */
5571        old = pg_default_opt;
5572
5573        if (temp)
5574                pg_default_opt = PyStr_FromString(temp);
5575        else
5576        {
5577                Py_INCREF(Py_None);
5578                pg_default_opt = Py_None;
5579        }
5580
5581        return old;
5582}
5583
5584/* gets default username */
5585static char pgGetDefUser__doc__[] =
5586"get_defuser() -- return default database username";
5587
5588static PyObject *
5589pgGetDefUser(PyObject *self, PyObject *noargs)
5590{
5591        Py_XINCREF(pg_default_user);
5592        return pg_default_user;
5593}
5594
5595/* sets default username */
5596
5597static char pgSetDefUser__doc__[] =
5598"set_defuser(name) -- set default username and return previous value";
5599
5600static PyObject *
5601pgSetDefUser(PyObject *self, PyObject *args)
5602{
5603        char       *temp = NULL;
5604        PyObject   *old;
5605
5606        /* gets arguments */
5607        if (!PyArg_ParseTuple(args, "z", &temp))
5608        {
5609                PyErr_SetString(PyExc_TypeError,
5610                        "Function set_defuser() expects a string or None as argument");
5611                return NULL;
5612        }
5613
5614        /* adjusts value */
5615        old = pg_default_user;
5616
5617        if (temp)
5618                pg_default_user = PyStr_FromString(temp);
5619        else
5620        {
5621                Py_INCREF(Py_None);
5622                pg_default_user = Py_None;
5623        }
5624
5625        return old;
5626}
5627
5628/* sets default password */
5629static char pgSetDefPassword__doc__[] =
5630"set_defpasswd(password) -- set default database password";
5631
5632static PyObject *
5633pgSetDefPassword(PyObject *self, PyObject *args)
5634{
5635        char       *temp = NULL;
5636
5637        /* gets arguments */
5638        if (!PyArg_ParseTuple(args, "z", &temp))
5639        {
5640                PyErr_SetString(PyExc_TypeError,
5641                        "Function set_defpasswd() expects a string or None as argument");
5642                return NULL;
5643        }
5644
5645        if (temp)
5646                pg_default_passwd = PyStr_FromString(temp);
5647        else
5648        {
5649                Py_INCREF(Py_None);
5650                pg_default_passwd = Py_None;
5651        }
5652
5653        Py_INCREF(Py_None);
5654        return Py_None;
5655}
5656
5657/* gets default port */
5658static char pgGetDefPort__doc__[] =
5659"get_defport() -- return default database port";
5660
5661static PyObject *
5662pgGetDefPort(PyObject *self, PyObject *noargs)
5663{
5664        Py_XINCREF(pg_default_port);
5665        return pg_default_port;
5666}
5667
5668/* sets default port */
5669static char pgSetDefPort__doc__[] =
5670"set_defport(port) -- set default port and return previous value";
5671
5672static PyObject *
5673pgSetDefPort(PyObject *self, PyObject *args)
5674{
5675        long int        port = -2;
5676        PyObject   *old;
5677
5678        /* gets arguments */
5679        if ((!PyArg_ParseTuple(args, "l", &port)) || (port < -1))
5680        {
5681                PyErr_SetString(PyExc_TypeError,
5682                        "Function set_deport expects"
5683                         " a positive integer or -1 as argument");
5684                return NULL;
5685        }
5686
5687        /* adjusts value */
5688        old = pg_default_port;
5689
5690        if (port != -1)
5691                pg_default_port = PyInt_FromLong(port);
5692        else
5693        {
5694                Py_INCREF(Py_None);
5695                pg_default_port = Py_None;
5696        }
5697
5698        return old;
5699}
5700#endif /* DEFAULT_VARS */
5701
5702/* cast a string with a text representation of an array to a list */
5703static char pgCastArray__doc__[] =
5704"cast_array(string, cast=None, delim=',') -- cast a string as an array";
5705
5706PyObject *
5707pgCastArray(PyObject *self, PyObject *args, PyObject *dict)
5708{
5709        static const char *kwlist[] = {"string", "cast", "delim", NULL};
5710        PyObject   *string_obj, *cast_obj = NULL, *ret;
5711        char       *string, delim = ',';
5712        Py_ssize_t      size;
5713        int                     encoding;
5714
5715        if (!PyArg_ParseTupleAndKeywords(args, dict, "O|Oc",
5716                        (char **) kwlist, &string_obj, &cast_obj, &delim))
5717                return NULL;
5718
5719        if (PyBytes_Check(string_obj))
5720        {
5721                PyBytes_AsStringAndSize(string_obj, &string, &size);
5722                string_obj = NULL;
5723                encoding = pg_encoding_ascii;
5724        }
5725        else if (PyUnicode_Check(string_obj))
5726        {
5727                string_obj = PyUnicode_AsUTF8String(string_obj);
5728                if (!string_obj) return NULL; /* pass the UnicodeEncodeError */
5729                PyBytes_AsStringAndSize(string_obj, &string, &size);
5730                encoding = pg_encoding_utf8;
5731        }
5732        else
5733        {
5734                PyErr_SetString(PyExc_TypeError,
5735                        "Function cast_array() expects a string as first argument");
5736                return NULL;
5737        }
5738
5739        if (!cast_obj || cast_obj == Py_None)
5740        {
5741                if (cast_obj)
5742                {
5743                        Py_DECREF(cast_obj); cast_obj = NULL;
5744                }
5745        }
5746        else if (!PyCallable_Check(cast_obj))
5747        {
5748                PyErr_SetString(PyExc_TypeError,
5749                        "Function cast_array() expects a callable as second argument");
5750                return NULL;
5751        }
5752
5753        ret = cast_array(string, size, encoding, 0, cast_obj, delim);
5754
5755        Py_XDECREF(string_obj);
5756
5757        return ret;
5758}
5759
5760/* cast a string with a text representation of a record to a tuple */
5761static char pgCastRecord__doc__[] =
5762"cast_record(string, cast=None, delim=',') -- cast a string as a record";
5763
5764PyObject *
5765pgCastRecord(PyObject *self, PyObject *args, PyObject *dict)
5766{
5767        static const char *kwlist[] = {"string", "cast", "delim", NULL};
5768        PyObject   *string_obj, *cast_obj = NULL, *ret;
5769        char       *string, delim = ',';
5770        Py_ssize_t      size, len;
5771        int                     encoding;
5772
5773        if (!PyArg_ParseTupleAndKeywords(args, dict, "O|Oc",
5774                        (char **) kwlist, &string_obj, &cast_obj, &delim))
5775                return NULL;
5776
5777        if (PyBytes_Check(string_obj))
5778        {
5779                PyBytes_AsStringAndSize(string_obj, &string, &size);
5780                string_obj = NULL;
5781                encoding = pg_encoding_ascii;
5782        }
5783        else if (PyUnicode_Check(string_obj))
5784        {
5785                string_obj = PyUnicode_AsUTF8String(string_obj);
5786                if (!string_obj) return NULL; /* pass the UnicodeEncodeError */
5787                PyBytes_AsStringAndSize(string_obj, &string, &size);
5788                encoding = pg_encoding_utf8;
5789        }
5790        else
5791        {
5792                PyErr_SetString(PyExc_TypeError,
5793                        "Function cast_record() expects a string as first argument");
5794                return NULL;
5795        }
5796
5797        if (!cast_obj || PyCallable_Check(cast_obj))
5798        {
5799                len = 0;
5800        }
5801        else if (cast_obj == Py_None)
5802        {
5803                Py_DECREF(cast_obj); cast_obj = NULL; len = 0;
5804        }
5805        else if (PyTuple_Check(cast_obj) || PyList_Check(cast_obj))
5806        {
5807                len = PySequence_Size(cast_obj);
5808                if (!len)
5809                {
5810                        Py_DECREF(cast_obj); cast_obj = NULL;
5811                }
5812        }
5813        else
5814        {
5815                PyErr_SetString(PyExc_TypeError,
5816                        "Function cast_record() expects a callable"
5817                         " or tuple or list of callables as second argument");
5818                return NULL;
5819        }
5820
5821        ret = cast_record(string, size, encoding, 0, cast_obj, len, delim);
5822
5823        Py_XDECREF(string_obj);
5824
5825        return ret;
5826}
5827
5828/* cast a string with a text representation of an hstore to a dict */
5829static char pgCastHStore__doc__[] =
5830"cast_hstore(string) -- cast a string as an hstore";
5831
5832PyObject *
5833pgCastHStore(PyObject *self, PyObject *string)
5834{
5835        PyObject   *tmp_obj = NULL, *ret;
5836        char       *s;
5837        Py_ssize_t      size;
5838        int                     encoding;
5839
5840        if (PyBytes_Check(string))
5841        {
5842                PyBytes_AsStringAndSize(string, &s, &size);
5843                encoding = pg_encoding_ascii;
5844        }
5845        else if (PyUnicode_Check(string))
5846        {
5847                tmp_obj = PyUnicode_AsUTF8String(string);
5848                if (!tmp_obj) return NULL; /* pass the UnicodeEncodeError */
5849                PyBytes_AsStringAndSize(tmp_obj, &s, &size);
5850                encoding = pg_encoding_utf8;
5851        }
5852        else
5853        {
5854                PyErr_SetString(PyExc_TypeError,
5855                        "Function cast_hstore() expects a string as first argument");
5856                return NULL;
5857        }
5858
5859        ret = cast_hstore(s, size, encoding);
5860
5861        Py_XDECREF(tmp_obj);
5862
5863        return ret;
5864}
5865
5866/* List of functions defined in the module */
5867
5868static struct PyMethodDef pgMethods[] = {
5869        {"connect", (PyCFunction) pgConnect, METH_VARARGS|METH_KEYWORDS,
5870                        pgConnect__doc__},
5871        {"escape_string", (PyCFunction) pgEscapeString, METH_O,
5872                        pgEscapeString__doc__},
5873        {"escape_bytea", (PyCFunction) pgEscapeBytea, METH_O,
5874                        pgEscapeBytea__doc__},
5875        {"unescape_bytea", (PyCFunction) pgUnescapeBytea, METH_O,
5876                        pgUnescapeBytea__doc__},
5877        {"get_datestyle", (PyCFunction) pgGetDatestyle, METH_NOARGS,
5878                        pgGetDatestyle__doc__},
5879        {"set_datestyle", (PyCFunction) pgSetDatestyle, METH_VARARGS,
5880                        pgSetDatestyle__doc__},
5881        {"get_decimal_point", (PyCFunction) pgGetDecimalPoint, METH_NOARGS,
5882                        pgGetDecimalPoint__doc__},
5883        {"set_decimal_point", (PyCFunction) pgSetDecimalPoint, METH_VARARGS,
5884                        pgSetDecimalPoint__doc__},
5885        {"get_decimal", (PyCFunction) pgGetDecimal, METH_NOARGS,
5886                        pgGetDecimal__doc__},
5887        {"set_decimal", (PyCFunction) pgSetDecimal, METH_O,
5888                        pgSetDecimal__doc__},
5889        {"get_bool", (PyCFunction) pgGetBool, METH_NOARGS, pgGetBool__doc__},
5890        {"set_bool", (PyCFunction) pgSetBool, METH_VARARGS, pgSetBool__doc__},
5891        {"get_array", (PyCFunction) pgGetArray, METH_NOARGS, pgGetArray__doc__},
5892        {"set_array", (PyCFunction) pgSetArray, METH_VARARGS, pgSetArray__doc__},
5893        {"get_bytea_escaped", (PyCFunction) pgGetByteaEscaped, METH_NOARGS,
5894                pgGetByteaEscaped__doc__},
5895        {"set_bytea_escaped", (PyCFunction) pgSetByteaEscaped, METH_VARARGS,
5896                pgSetByteaEscaped__doc__},
5897        {"get_namedresult", (PyCFunction) pgGetNamedresult, METH_NOARGS,
5898                        pgGetNamedresult__doc__},
5899        {"set_namedresult", (PyCFunction) pgSetNamedresult, METH_O,
5900                        pgSetNamedresult__doc__},
5901        {"get_jsondecode", (PyCFunction) pgGetJsondecode, METH_NOARGS,
5902                        pgGetJsondecode__doc__},
5903        {"set_jsondecode", (PyCFunction) pgSetJsondecode, METH_O,
5904                        pgSetJsondecode__doc__},
5905        {"cast_array", (PyCFunction) pgCastArray, METH_VARARGS|METH_KEYWORDS,
5906                        pgCastArray__doc__},
5907        {"cast_record", (PyCFunction) pgCastRecord, METH_VARARGS|METH_KEYWORDS,
5908                        pgCastRecord__doc__},
5909        {"cast_hstore", (PyCFunction) pgCastHStore, METH_O, pgCastHStore__doc__},
5910
5911#ifdef DEFAULT_VARS
5912        {"get_defhost", pgGetDefHost, METH_NOARGS, pgGetDefHost__doc__},
5913        {"set_defhost", pgSetDefHost, METH_VARARGS, pgSetDefHost__doc__},
5914        {"get_defbase", pgGetDefBase, METH_NOARGS, pgGetDefBase__doc__},
5915        {"set_defbase", pgSetDefBase, METH_VARARGS, pgSetDefBase__doc__},
5916        {"get_defopt", pgGetDefOpt, METH_NOARGS, pgGetDefOpt__doc__},
5917        {"set_defopt", pgSetDefOpt, METH_VARARGS, pgSetDefOpt__doc__},
5918        {"get_defport", pgGetDefPort, METH_NOARGS, pgGetDefPort__doc__},
5919        {"set_defport", pgSetDefPort, METH_VARARGS, pgSetDefPort__doc__},
5920        {"get_defuser", pgGetDefUser, METH_NOARGS, pgGetDefUser__doc__},
5921        {"set_defuser", pgSetDefUser, METH_VARARGS, pgSetDefUser__doc__},
5922        {"set_defpasswd", pgSetDefPassword, METH_VARARGS, pgSetDefPassword__doc__},
5923#endif /* DEFAULT_VARS */
5924        {NULL, NULL} /* sentinel */
5925};
5926
5927static char pg__doc__[] = "Python interface to PostgreSQL DB";
5928
5929static struct PyModuleDef moduleDef = {
5930        PyModuleDef_HEAD_INIT,
5931        "_pg",          /* m_name */
5932        pg__doc__,      /* m_doc */
5933        -1,                     /* m_size */
5934        pgMethods       /* m_methods */
5935};
5936
5937/* Initialization function for the module */
5938MODULE_INIT_FUNC(_pg)
5939{
5940        PyObject   *mod, *dict, *s;
5941
5942        /* Create the module and add the functions */
5943
5944        mod = PyModule_Create(&moduleDef);
5945
5946        /* Initialize here because some Windows platforms get confused otherwise */
5947#if IS_PY3
5948        connType.tp_base = noticeType.tp_base =
5949                queryType.tp_base = sourceType.tp_base = &PyBaseObject_Type;
5950#ifdef LARGE_OBJECTS
5951        largeType.tp_base = &PyBaseObject_Type;
5952#endif
5953#else
5954        connType.ob_type = noticeType.ob_type =
5955                queryType.ob_type = sourceType.ob_type = &PyType_Type;
5956#ifdef LARGE_OBJECTS
5957        largeType.ob_type = &PyType_Type;
5958#endif
5959#endif
5960
5961        if (PyType_Ready(&connType)
5962                || PyType_Ready(&noticeType)
5963                || PyType_Ready(&queryType)
5964                || PyType_Ready(&sourceType)
5965#ifdef LARGE_OBJECTS
5966                || PyType_Ready(&largeType)
5967#endif
5968                ) return NULL;
5969
5970        dict = PyModule_GetDict(mod);
5971
5972        /* Exceptions as defined by DB-API 2.0 */
5973        Error = PyErr_NewException("pg.Error", PyExc_Exception, NULL);
5974        PyDict_SetItemString(dict, "Error", Error);
5975
5976        Warning = PyErr_NewException("pg.Warning", PyExc_Exception, NULL);
5977        PyDict_SetItemString(dict, "Warning", Warning);
5978
5979        InterfaceError = PyErr_NewException("pg.InterfaceError", Error, NULL);
5980        PyDict_SetItemString(dict, "InterfaceError", InterfaceError);
5981
5982        DatabaseError = PyErr_NewException("pg.DatabaseError", Error, NULL);
5983        PyDict_SetItemString(dict, "DatabaseError", DatabaseError);
5984
5985        InternalError = PyErr_NewException("pg.InternalError", DatabaseError, NULL);
5986        PyDict_SetItemString(dict, "InternalError", InternalError);
5987
5988        OperationalError =
5989                PyErr_NewException("pg.OperationalError", DatabaseError, NULL);
5990        PyDict_SetItemString(dict, "OperationalError", OperationalError);
5991
5992        ProgrammingError =
5993                PyErr_NewException("pg.ProgrammingError", DatabaseError, NULL);
5994        PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError);
5995
5996        IntegrityError =
5997                PyErr_NewException("pg.IntegrityError", DatabaseError, NULL);
5998        PyDict_SetItemString(dict, "IntegrityError", IntegrityError);
5999
6000        DataError = PyErr_NewException("pg.DataError", DatabaseError, NULL);
6001        PyDict_SetItemString(dict, "DataError", DataError);
6002
6003        NotSupportedError =
6004                PyErr_NewException("pg.NotSupportedError", DatabaseError, NULL);
6005        PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError);
6006
6007        /* Make the version available */
6008        s = PyStr_FromString(PyPgVersion);
6009        PyDict_SetItemString(dict, "version", s);
6010        PyDict_SetItemString(dict, "__version__", s);
6011        Py_DECREF(s);
6012
6013        /* results type for queries */
6014        PyDict_SetItemString(dict, "RESULT_EMPTY", PyInt_FromLong(RESULT_EMPTY));
6015        PyDict_SetItemString(dict, "RESULT_DML", PyInt_FromLong(RESULT_DML));
6016        PyDict_SetItemString(dict, "RESULT_DDL", PyInt_FromLong(RESULT_DDL));
6017        PyDict_SetItemString(dict, "RESULT_DQL", PyInt_FromLong(RESULT_DQL));
6018
6019        /* transaction states */
6020        PyDict_SetItemString(dict,"TRANS_IDLE",PyInt_FromLong(PQTRANS_IDLE));
6021        PyDict_SetItemString(dict,"TRANS_ACTIVE",PyInt_FromLong(PQTRANS_ACTIVE));
6022        PyDict_SetItemString(dict,"TRANS_INTRANS",PyInt_FromLong(PQTRANS_INTRANS));
6023        PyDict_SetItemString(dict,"TRANS_INERROR",PyInt_FromLong(PQTRANS_INERROR));
6024        PyDict_SetItemString(dict,"TRANS_UNKNOWN",PyInt_FromLong(PQTRANS_UNKNOWN));
6025
6026#ifdef LARGE_OBJECTS
6027        /* create mode for large objects */
6028        PyDict_SetItemString(dict, "INV_READ", PyInt_FromLong(INV_READ));
6029        PyDict_SetItemString(dict, "INV_WRITE", PyInt_FromLong(INV_WRITE));
6030
6031        /* position flags for lo_lseek */
6032        PyDict_SetItemString(dict, "SEEK_SET", PyInt_FromLong(SEEK_SET));
6033        PyDict_SetItemString(dict, "SEEK_CUR", PyInt_FromLong(SEEK_CUR));
6034        PyDict_SetItemString(dict, "SEEK_END", PyInt_FromLong(SEEK_END));
6035#endif /* LARGE_OBJECTS */
6036
6037#ifdef DEFAULT_VARS
6038        /* prepares default values */
6039        Py_INCREF(Py_None);
6040        pg_default_host = Py_None;
6041        Py_INCREF(Py_None);
6042        pg_default_base = Py_None;
6043        Py_INCREF(Py_None);
6044        pg_default_opt = Py_None;
6045        Py_INCREF(Py_None);
6046        pg_default_port = Py_None;
6047        Py_INCREF(Py_None);
6048        pg_default_user = Py_None;
6049        Py_INCREF(Py_None);
6050        pg_default_passwd = Py_None;
6051#endif /* DEFAULT_VARS */
6052
6053        /* store common pg encoding ids */
6054
6055        pg_encoding_utf8 = pg_char_to_encoding("UTF8");
6056        pg_encoding_latin1 = pg_char_to_encoding("LATIN1");
6057        pg_encoding_ascii = pg_char_to_encoding("SQL_ASCII");
6058
6059        /* Check for errors */
6060        if (PyErr_Occurred())
6061                return NULL;
6062
6063        return mod;
6064}
Note: See TracBrowser for help on using the repository browser.