source: trunk/pgmodule.c @ 814

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

Add typecasting of dates, times, timestamps, intervals

So far, PyGreSQL has returned these types only as strings (in various
formats depending on the DateStyle? setting) and left it to the user
to parse and interpret the strings. These types are now properly cast
into the corresponding detetime types of Python, and this works with
any setting of DatesStyle?, even if you change DateStyle? in the middle
of a database session.

To implement this, a fast method for getting the datestyle (cached and
without roundtrip to the database) has been added. Also, the typecast
mechanism has been extended so that typecast functions can optionally
also take the connection as argument.

The date and time typecast functions have been implemented in Python
using the new typecast registry and added to both pg and pgdb. Some
duplication of code in the two modules was unavoidable, since we don't
want the modules to be dependent of each other or install additional
helper modules. One day we might want to change this, put everything
in one package and factor out some of the functionality.

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