source: trunk/pgmodule.c

Last change on this file was 957, checked in by cito, 7 weeks ago

Add documentation for prepared statements

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