source: trunk/pgmodule.c @ 813

Last change on this file since 813 was 813, checked in by cito, 4 years ago

Make better use of ml_flags in the C module

This made the code a bit cleaner and smaller.

Also adapted some tests that still assumed set_bool(False).

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