source: branches/4.x/pgmodule.c @ 943

Last change on this file since 943 was 926, checked in by cito, 20 months ago

Use-after-free bug in query function implementation

  • Property svn:keywords set to Id
File size: 101.0 KB
Line 
1/*
2 * $Id: pgmodule.c 926 2018-01-22 08:21:18Z darcy $
3 * PyGres, version 2.2 A Python interface for PostgreSQL database. Written by
4 * D'Arcy J.M. Cain, (darcy@druid.net).  Based heavily on code written by
5 * Pascal Andre, andre@chimay.via.ecp.fr. Copyright (c) 1995, Pascal Andre
6 * (andre@via.ecp.fr).
7 *
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation for any purpose, without fee, and without a written
10 * agreement is hereby granted, provided that the above copyright notice and
11 * this paragraph and the following two paragraphs appear in all copies or in
12 * any new file that contains a substantial portion of this file.
13 *
14 * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
15 * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
17 * AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18 *
19 * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE
22 * AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
23 * ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Further modifications copyright 1997 to 2016 by D'Arcy J.M. Cain
26 * (darcy@druid.net) 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#include <Python.h>
32
33#include <libpq-fe.h>
34
35/* some definitions from <libpq/libpq-fs.h> */
36#include "pgfs.h"
37/* the type definitions from <catalog/pg_type.h> */
38#include "pgtypes.h"
39
40static PyObject *Error, *Warning, *InterfaceError,
41        *DatabaseError, *InternalError, *OperationalError, *ProgrammingError,
42        *IntegrityError, *DataError, *NotSupportedError;
43
44#define _TOSTRING(x) #x
45#define TOSTRING(x) _TOSTRING(x)
46static const char *PyPgVersion = TOSTRING(PYGRESQL_VERSION);
47
48#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
49typedef int Py_ssize_t;
50#define PY_SSIZE_T_MAX INT_MAX
51#define PY_SSIZE_T_MIN INT_MIN
52#endif
53
54#if PY_VERSION_HEX >= 0x02050000 && SIZEOF_SIZE_T != SIZEOF_INT
55#define Py_InitModule4 Py_InitModule4_64
56#endif
57
58/* taken from fileobject.c */
59#define BUF(v) PyString_AS_STRING((PyStringObject *)(v))
60
61/* default values */
62#define MODULE_NAME                     "pgsql"
63#define PG_ARRAYSIZE                    1
64
65/* flags for object validity checks */
66#define CHECK_OPEN                      1
67#define CHECK_CLOSE                     2
68#define CHECK_CNX                       4
69#define CHECK_RESULT            8
70#define CHECK_DQL                       16
71
72/* query result types */
73#define RESULT_EMPTY            1
74#define RESULT_DML                      2
75#define RESULT_DDL                      3
76#define RESULT_DQL                      4
77
78/* flags for move methods */
79#define QUERY_MOVEFIRST         1
80#define QUERY_MOVELAST          2
81#define QUERY_MOVENEXT          3
82#define QUERY_MOVEPREV          4
83
84/* moves names for errors */
85const char *__movename[5] =
86{"", "movefirst", "movelast", "movenext", "moveprev"};
87
88#define MAX_BUFFER_SIZE 8192    /* maximum transaction size */
89
90#ifndef PG_VERSION_NUM
91#ifdef PQnoPasswordSupplied
92#define PG_VERSION_NUM 80000
93#else
94#define PG_VERSION_NUM 70400
95#endif
96#endif
97
98/* Before 8.0, PQsetdbLogin was not thread-safe with kerberos. */
99#if PG_VERSION_NUM >= 80000 || !(defined(KRB4) || defined(KRB5))
100#define PQsetdbLoginIsThreadSafe 1
101#endif
102
103/* --------------------------------------------------------------------- */
104
105/* MODULE GLOBAL VARIABLES */
106
107#ifdef DEFAULT_VARS
108static PyObject *pg_default_host;       /* default database host */
109static PyObject *pg_default_base;       /* default database name */
110static PyObject *pg_default_opt;        /* default connection options */
111static PyObject *pg_default_tty;        /* default debug tty */
112static PyObject *pg_default_port;       /* default connection port */
113static PyObject *pg_default_user;       /* default username */
114static PyObject *pg_default_passwd;     /* default password */
115#endif  /* DEFAULT_VARS */
116
117DL_EXPORT(void) init_pg(void);
118int *get_type_array(PGresult *result, int nfields);
119
120static PyObject *decimal = NULL, /* decimal type */
121                                *namedresult = NULL; /* function for getting named results */
122static char decimal_point = '.'; /* decimal point used in money values */
123static int use_bool = 0; /* whether or not bool objects shall be returned */
124
125/* --------------------------------------------------------------------- */
126/* OBJECTS DECLARATION */
127
128/* pg connection object */
129
130typedef struct
131{
132        PyObject_HEAD
133        int                     valid;                          /* validity flag */
134        PGconn          *cnx;                           /* PostGres connection handle */
135        PyObject        *notice_receiver;       /* current notice receiver */
136}       pgobject;
137
138staticforward PyTypeObject PgType;
139
140#define is_pgobject(v) ((v)->ob_type == &PgType)
141
142static PyObject *
143pgobject_New(void)
144{
145        pgobject        *pgobj;
146
147        if (!(pgobj = PyObject_NEW(pgobject, &PgType)))
148                return NULL;
149
150        pgobj->valid = 1;
151        pgobj->cnx = NULL;
152        pgobj->notice_receiver = NULL;
153
154        return (PyObject *) pgobj;
155}
156
157/* pg notice result object */
158
159typedef struct
160{
161        PyObject_HEAD
162        pgobject        *pgcnx;         /* parent connection object */
163        PGresult        const *res;     /* an error or warning */
164}       pgnoticeobject;
165
166staticforward PyTypeObject PgNoticeType;
167
168#define is_pgnoticeobject(v) ((v)->ob_type == &PgNoticeType)
169
170/* pg query object */
171
172typedef struct
173{
174        PyObject_HEAD
175        PGresult        *result;                /* result content */
176        int                     result_type;    /* type of previous result */
177        long            current_pos;    /* current position in last result */
178        long            num_rows;               /* number of (affected) rows */
179}       pgqueryobject;
180
181staticforward PyTypeObject PgQueryType;
182
183#define is_pgqueryobject(v) ((v)->ob_type == &PgQueryType)
184
185/* pg source object */
186
187typedef struct
188{
189        PyObject_HEAD
190        int                     valid;                  /* validity flag */
191        pgobject        *pgcnx;                 /* parent connection object */
192        PGresult        *result;                /* result content */
193        int                     result_type;    /* result type (DDL/DML/DQL) */
194        long            arraysize;              /* array size for fetch method */
195        int                     current_row;    /* current selected row */
196        int                     max_row;                /* number of rows in the result */
197        int                     num_fields;             /* number of fields in each row */
198}       pgsourceobject;
199
200staticforward PyTypeObject PgSourceType;
201
202#define is_pgsourceobject(v) ((v)->ob_type == &PgSourceType)
203
204
205#ifdef LARGE_OBJECTS
206/* pg large object */
207
208typedef struct
209{
210        PyObject_HEAD
211        pgobject        *pgcnx;                 /* parent connection object */
212        Oid                     lo_oid;                 /* large object oid */
213        int                     lo_fd;                  /* large object fd */
214}       pglargeobject;
215
216staticforward PyTypeObject PglargeType;
217
218#define is_pglargeobject(v) ((v)->ob_type == &PglargeType)
219#endif /* LARGE_OBJECTS */
220
221/* --------------------------------------------------------------------- */
222/* INTERNAL FUNCTIONS */
223
224/* sets database error with sqlstate attribute */
225/* This should be used when raising a subclass of DatabaseError */
226static void
227set_dberror(PyObject *type, const char *msg, PGresult *result)
228{
229        PyObject *err = NULL;
230        PyObject *str;
231
232        if (!(str = PyString_FromString(msg)))
233                err = NULL;
234        else
235        {
236                err = PyObject_CallFunctionObjArgs(type, str, NULL);
237                Py_DECREF(str);
238        }
239        if (err)
240        {
241                if (result)
242                {
243                        char *sqlstate = PQresultErrorField(result, PG_DIAG_SQLSTATE);
244                        str = sqlstate ? PyString_FromStringAndSize(sqlstate, 5) : NULL;
245                }
246                else
247                        str = NULL;
248                if (!str)
249                {
250                        Py_INCREF(Py_None);
251                        str = Py_None;
252                }
253                PyObject_SetAttrString(err, "sqlstate", str);
254                Py_DECREF(str);
255                PyErr_SetObject(type, err);
256                Py_DECREF(err);
257        }
258        else
259                PyErr_SetString(type, msg);
260}
261
262
263/* checks connection validity */
264static int
265check_cnx_obj(pgobject *self)
266{
267        if (!self->valid)
268        {
269                set_dberror(OperationalError, "connection has been closed.", NULL);
270                return 0;
271        }
272        return 1;
273}
274
275#ifdef LARGE_OBJECTS
276/* checks large object validity */
277static int
278check_lo_obj(pglargeobject *self, int level)
279{
280        if (!check_cnx_obj(self->pgcnx))
281                return 0;
282
283        if (!self->lo_oid)
284        {
285                set_dberror(IntegrityError, "object is not valid (null oid).", NULL);
286                return 0;
287        }
288
289        if (level & CHECK_OPEN)
290        {
291                if (self->lo_fd < 0)
292                {
293                        PyErr_SetString(PyExc_IOError, "object is not opened.");
294                        return 0;
295                }
296        }
297
298        if (level & CHECK_CLOSE)
299        {
300                if (self->lo_fd >= 0)
301                {
302                        PyErr_SetString(PyExc_IOError, "object is already opened.");
303                        return 0;
304                }
305        }
306
307        return 1;
308}
309#endif /* LARGE_OBJECTS */
310
311/* checks source object validity */
312static int
313check_source_obj(pgsourceobject *self, int level)
314{
315        if (!self->valid)
316        {
317                set_dberror(OperationalError, "object has been closed", NULL);
318                return 0;
319        }
320
321        if ((level & CHECK_RESULT) && !self->result)
322        {
323                set_dberror(DatabaseError, "no result.", NULL);
324                return 0;
325        }
326
327        if ((level & CHECK_DQL) && self->result_type != RESULT_DQL)
328        {
329                set_dberror(DatabaseError,
330                        "last query did not return tuples.", self->result);
331                return 0;
332        }
333
334        if ((level & CHECK_CNX) && !check_cnx_obj(self->pgcnx))
335                return 0;
336
337        return 1;
338}
339
340/* define internal types */
341
342#define PYGRES_INT 1
343#define PYGRES_LONG 2
344#define PYGRES_FLOAT 3
345#define PYGRES_DECIMAL 4
346#define PYGRES_MONEY 5
347#define PYGRES_BOOL 6
348#define PYGRES_DEFAULT 7
349
350/* shared functions for converting PG types to Python types */
351int *
352get_type_array(PGresult *result, int nfields)
353{
354        int *typ;
355        int j;
356
357        if (!(typ = PyMem_Malloc(sizeof(int) * nfields)))
358        {
359                PyErr_SetString(PyExc_MemoryError, "memory error in getresult().");
360                return NULL;
361        }
362
363        for (j = 0; j < nfields; j++)
364        {
365                switch (PQftype(result, j))
366                {
367                        case INT2OID:
368                        case INT4OID:
369                        case OIDOID:
370                                typ[j] = PYGRES_INT;
371                                break;
372
373                        case INT8OID:
374                                typ[j] = PYGRES_LONG;
375                                break;
376
377                        case FLOAT4OID:
378                        case FLOAT8OID:
379                                typ[j] = PYGRES_FLOAT;
380                                break;
381
382                        case NUMERICOID:
383                                typ[j] = PYGRES_DECIMAL;
384                                break;
385
386                        case CASHOID:
387                                typ[j] = PYGRES_MONEY;
388                                break;
389
390                        case BOOLOID:
391                                typ[j] = PYGRES_BOOL;
392                                break;
393
394                        default:
395                                typ[j] = PYGRES_DEFAULT;
396                                break;
397                }
398        }
399
400        return typ;
401}
402
403/* format result (mostly useful for debugging) */
404/* Note: This is similar to the Postgres function PQprint().
405 * PQprint() is not used because handing over a stream from Python to
406 * Postgres can be problematic if they use different libs for streams
407 * and because using PQprint() and tp_print is not recommended any more.
408 */
409
410static PyObject *
411format_result(const PGresult *res)
412{
413        const int n = PQnfields(res);
414
415        if (n > 0)
416        {
417                char * const aligns = (char *) PyMem_Malloc(n * sizeof(char));
418                int * const sizes = (int *) PyMem_Malloc(n * sizeof(int));
419
420                if (aligns && sizes)
421                {
422                        const int m = PQntuples(res);
423                        int i, j;
424                        size_t size;
425                        char *buffer;
426
427                        /* calculate sizes and alignments */
428                        for (j = 0; j < n; j++)
429                        {
430                                const char * const s = PQfname(res, j);
431                                const int format = PQfformat(res, j);
432
433                                sizes[j] = s ? (int)strlen(s) : 0;
434                                if (format)
435                                {
436                                        aligns[j] = '\0';
437                                        if (m && sizes[j] < 8)
438                                                /* "<binary>" must fit */
439                                                sizes[j] = 8;
440                                }
441                                else
442                                {
443                                        const Oid ftype = PQftype(res, j);
444
445                                        switch (ftype)
446                                        {
447                                                case INT2OID:
448                                                case INT4OID:
449                                                case INT8OID:
450                                                case FLOAT4OID:
451                                                case FLOAT8OID:
452                                                case NUMERICOID:
453                                                case OIDOID:
454                                                case XIDOID:
455                                                case CIDOID:
456                                                case CASHOID:
457                                                        aligns[j] = 'r';
458                                                        break;
459                                                default:
460                                                        aligns[j] = 'l';
461                                                        break;
462                                        }
463                                }
464                        }
465                        for (i = 0; i < m; i++)
466                        {
467                                for (j = 0; j < n; j++)
468                                {
469                                        if (aligns[j])
470                                        {
471                                                const int k = PQgetlength(res, i, j);
472
473                                                if (sizes[j] < k)
474                                                        /* value must fit */
475                                                        sizes[j] = k;
476                                        }
477                                }
478                        }
479                        size = 0;
480                        /* size of one row */
481                        for (j = 0; j < n; j++) size += sizes[j] + 1;
482                        /* times number of rows incl. heading */
483                        size *= (m + 2);
484                        /* plus size of footer */
485                        size += 40;
486                        /* is the buffer size that needs to be allocated */
487                        buffer = (char *) PyMem_Malloc(size);
488                        if (buffer)
489                        {
490                                char *p = buffer;
491                                PyObject *result;
492
493                                /* create the header */
494                                for (j = 0; j < n; j++)
495                                {
496                                        const char * const s = PQfname(res, j);
497                                        const int k = sizes[j];
498                                        const int h = (k - (int)strlen(s)) / 2;
499
500                                        sprintf(p, "%*s", h, "");
501                                        sprintf(p + h, "%-*s", k - h, s);
502                                        p += k;
503                                        if (j + 1 < n)
504                                                *p++ = '|';
505                                }
506                                *p++ = '\n';
507                                for (j = 0; j < n; j++)
508                                {
509                                        int k = sizes[j];
510
511                                        while (k--)
512                                                *p++ = '-';
513                                        if (j + 1 < n)
514                                                *p++ = '+';
515                                }
516                                *p++ = '\n';
517                                /* create the body */
518                                for (i = 0; i < m; i++)
519                                {
520                                        for (j = 0; j < n; j++)
521                                        {
522                                                const char align = aligns[j];
523                                                const int k = sizes[j];
524
525                                                if (align)
526                                                {
527                                                        sprintf(p, align == 'r' ?
528                                                                "%*s" : "%-*s", k,
529                                                                PQgetvalue(res, i, j));
530                                                }
531                                                else
532                                                {
533                                                        sprintf(p, "%-*s", k,
534                                                                PQgetisnull(res, i, j) ?
535                                                                "" : "<binary>");
536                                                }
537                                                p += k;
538                                                if (j + 1 < n)
539                                                        *p++ = '|';
540                                        }
541                                        *p++ = '\n';
542                                }
543                                /* free memory */
544                                PyMem_Free(aligns);
545                                PyMem_Free(sizes);
546                                /* create the footer */
547                                sprintf(p, "(%d row%s)", m, m == 1 ? "" : "s");
548                                /* return the result */
549                                result = PyString_FromString(buffer);
550                                PyMem_Free(buffer);
551                                return result;
552                        }
553                        else
554                        {
555                                PyErr_SetString(PyExc_MemoryError,
556                                        "Not enough memory for formatting the query result.");
557                                return NULL;
558                        }
559                } else {
560                        PyMem_Free(aligns);
561                        PyMem_Free(sizes);
562                        PyErr_SetString(PyExc_MemoryError,
563                                "Not enough memory for formatting the query result.");
564                        return NULL;
565                }
566        }
567        else
568                return PyString_FromString("(nothing selected)");
569}
570
571/* prototypes for constructors */
572static pgsourceobject *pgsource_new(pgobject *pgcnx);
573
574/* --------------------------------------------------------------------- */
575/* PG SOURCE OBJECT IMPLEMENTATION */
576
577/* constructor (internal use only) */
578static pgsourceobject *
579pgsource_new(pgobject *pgcnx)
580{
581        pgsourceobject *npgobj;
582
583        /* allocates new query object */
584        if (!(npgobj = PyObject_NEW(pgsourceobject, &PgSourceType)))
585                return NULL;
586
587        /* initializes internal parameters */
588        Py_XINCREF(pgcnx);
589        npgobj->pgcnx = pgcnx;
590        npgobj->result = NULL;
591        npgobj->valid = 1;
592        npgobj->arraysize = PG_ARRAYSIZE;
593
594        return npgobj;
595}
596
597/* destructor */
598static void
599pgsource_dealloc(pgsourceobject *self)
600{
601        if (self->result)
602                PQclear(self->result);
603
604        Py_XDECREF(self->pgcnx);
605        PyObject_Del(self);
606}
607
608/* closes object */
609static char pgsource_close__doc__[] =
610"close() -- close query object without deleting it. "
611"All instances of the query object can no longer be used after this call.";
612
613static PyObject *
614pgsource_close(pgsourceobject *self, PyObject *args)
615{
616        /* checks args */
617        if (!PyArg_ParseTuple(args, ""))
618        {
619                PyErr_SetString(PyExc_TypeError, "method close() takes no parameter.");
620                return NULL;
621        }
622
623        /* frees result if necessary and invalidates object */
624        if (self->result)
625        {
626                PQclear(self->result);
627                self->result_type = RESULT_EMPTY;
628                self->result = NULL;
629        }
630
631        self->valid = 0;
632
633        /* return None */
634        Py_INCREF(Py_None);
635        return Py_None;
636}
637
638/* database query */
639static char pgsource_execute__doc__[] =
640"execute(sql) -- execute a SQL statement (string).\n "
641"On success, this call returns the number of affected rows, "
642"or None for DQL (SELECT, ...) statements.\n"
643"The fetch (fetch(), fetchone() and fetchall()) methods can be used "
644"to get result rows.";
645
646static PyObject *
647pgsource_execute(pgsourceobject *self, PyObject *args)
648{
649        char            *query;
650
651        /* checks validity */
652        if (!check_source_obj(self, CHECK_CNX))
653                return NULL;
654
655        /* make sure that the connection object is valid */
656        if (!self->pgcnx->cnx)
657                return NULL;
658
659        /* get query args */
660        if (!PyArg_ParseTuple(args, "s", &query))
661        {
662                PyErr_SetString(PyExc_TypeError, "execute(sql), with sql (string).");
663                return NULL;
664        }
665
666        /* frees previous result */
667        if (self->result)
668        {
669                PQclear(self->result);
670                self->result = NULL;
671        }
672        self->max_row = 0;
673        self->current_row = 0;
674        self->num_fields = 0;
675
676        /* gets result */
677        Py_BEGIN_ALLOW_THREADS
678        self->result = PQexec(self->pgcnx->cnx, query);
679        Py_END_ALLOW_THREADS
680
681        /* checks result validity */
682        if (!self->result)
683        {
684                PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->pgcnx->cnx));
685                return NULL;
686        }
687
688        /* checks result status */
689        switch (PQresultStatus(self->result))
690        {
691                long    num_rows;
692                char   *temp;
693
694                /* query succeeded */
695                case PGRES_TUPLES_OK:   /* DQL: returns None (DB-SIG compliant) */
696                        self->result_type = RESULT_DQL;
697                        self->max_row = PQntuples(self->result);
698                        self->num_fields = PQnfields(self->result);
699                        Py_INCREF(Py_None);
700                        return Py_None;
701                case PGRES_COMMAND_OK:  /* other requests */
702                case PGRES_COPY_OUT:
703                case PGRES_COPY_IN:
704                        self->result_type = RESULT_DDL;
705                        temp = PQcmdTuples(self->result);
706                        num_rows = -1;
707                        if (temp[0])
708                        {
709                                self->result_type = RESULT_DML;
710                                num_rows = atol(temp);
711                        }
712                        return PyInt_FromLong(num_rows);
713
714                /* query failed */
715                case PGRES_EMPTY_QUERY:
716                        PyErr_SetString(PyExc_ValueError, "empty query.");
717                        break;
718                case PGRES_BAD_RESPONSE:
719                case PGRES_FATAL_ERROR:
720                case PGRES_NONFATAL_ERROR:
721                        set_dberror(ProgrammingError,
722                                PQerrorMessage(self->pgcnx->cnx), self->result);
723                        break;
724                default:
725                        set_dberror(InternalError, "internal error: "
726                                "unknown result status.", self->result);
727                        break;
728        }
729
730        /* frees result and returns error */
731        PQclear(self->result);
732        self->result = NULL;
733        self->result_type = RESULT_EMPTY;
734        return NULL;
735}
736
737/* gets oid status for last query (valid for INSERTs, 0 for other) */
738static char pgsource_oidstatus__doc__[] =
739"oidstatus() -- return oid of last inserted row (if available).";
740
741static PyObject *
742pgsource_oidstatus(pgsourceobject *self, PyObject *args)
743{
744        Oid                     oid;
745
746        /* checks validity */
747        if (!check_source_obj(self, CHECK_RESULT))
748                return NULL;
749
750        /* checks args */
751        if (args && !PyArg_ParseTuple(args, ""))
752        {
753                PyErr_SetString(PyExc_TypeError,
754                        "method oidstatus() takes no parameters.");
755                return NULL;
756        }
757
758        /* retrieves oid status */
759        if ((oid = PQoidValue(self->result)) == InvalidOid)
760        {
761                Py_INCREF(Py_None);
762                return Py_None;
763        }
764
765        return PyInt_FromLong(oid);
766}
767
768/* fetches rows from last result */
769static char pgsource_fetch__doc__[] =
770"fetch(num) -- return the next num rows from the last result in a list. "
771"If num parameter is omitted arraysize attribute value is used. "
772"If size equals -1, all rows are fetched.";
773
774static PyObject *
775pgsource_fetch(pgsourceobject *self, PyObject *args)
776{
777        PyObject   *rowtuple,
778                           *reslist,
779                           *str;
780        int                     i,
781                                j;
782        long            size;
783
784        /* checks validity */
785        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
786                return NULL;
787
788        /* checks args */
789        size = self->arraysize;
790        if (!PyArg_ParseTuple(args, "|l", &size))
791        {
792                PyErr_SetString(PyExc_TypeError,
793                        "fetch(num), with num (integer, optional).");
794                return NULL;
795        }
796
797        /* seeks last line */
798        /* limit size to be within the amount of data we actually have */
799        if (size == -1 || (self->max_row - self->current_row) < size)
800                size = self->max_row - self->current_row;
801
802        /* allocate list for result */
803        if (!(reslist = PyList_New(0)))
804                return NULL;
805
806        /* builds result */
807        for (i = 0; i < size; i++)
808        {
809                if (!(rowtuple = PyTuple_New(self->num_fields)))
810                {
811                        Py_DECREF(reslist);
812                        return NULL;
813                }
814
815                for (j = 0; j < self->num_fields; j++)
816                {
817                        if (PQgetisnull(self->result, self->current_row, j))
818                        {
819                                Py_INCREF(Py_None);
820                                str = Py_None;
821                        }
822                        else
823                                str = PyString_FromString(PQgetvalue(self->result, self->current_row, j));
824
825                        PyTuple_SET_ITEM(rowtuple, j, str);
826                }
827
828                PyList_Append(reslist, rowtuple);
829                Py_DECREF(rowtuple);
830                self->current_row++;
831        }
832
833        return reslist;
834}
835
836/* changes current row (internal wrapper for all "move" methods) */
837static PyObject *
838pgsource_move(pgsourceobject *self, PyObject *args, int move)
839{
840        /* checks validity */
841        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
842                return NULL;
843
844        /* checks args */
845        if (!PyArg_ParseTuple(args, ""))
846        {
847                char            errbuf[256];
848                PyOS_snprintf(errbuf, sizeof(errbuf),
849                        "method %s() takes no parameter.", __movename[move]);
850                PyErr_SetString(PyExc_TypeError, errbuf);
851                return NULL;
852        }
853
854        /* changes the current row */
855        switch (move)
856        {
857                case QUERY_MOVEFIRST:
858                        self->current_row = 0;
859                        break;
860                case QUERY_MOVELAST:
861                        self->current_row = self->max_row - 1;
862                        break;
863                case QUERY_MOVENEXT:
864                        if (self->current_row != self->max_row)
865                                self->current_row++;
866                        break;
867                case QUERY_MOVEPREV:
868                        if (self->current_row > 0)
869                                self->current_row--;
870                        break;
871        }
872
873        Py_INCREF(Py_None);
874        return Py_None;
875}
876
877/* move to first result row */
878static char pgsource_movefirst__doc__[] =
879"movefirst() -- move to first result row.";
880
881static PyObject *
882pgsource_movefirst(pgsourceobject *self, PyObject *args)
883{
884        return pgsource_move(self, args, QUERY_MOVEFIRST);
885}
886
887/* move to last result row */
888static char pgsource_movelast__doc__[] =
889"movelast() -- move to last valid result row.";
890
891static PyObject *
892pgsource_movelast(pgsourceobject *self, PyObject *args)
893{
894        return pgsource_move(self, args, QUERY_MOVELAST);
895}
896
897/* move to next result row */
898static char pgsource_movenext__doc__[] =
899"movenext() -- move to next result row.";
900
901static PyObject *
902pgsource_movenext(pgsourceobject *self, PyObject *args)
903{
904        return pgsource_move(self, args, QUERY_MOVENEXT);
905}
906
907/* move to previous result row */
908static char pgsource_moveprev__doc__[] =
909"moveprev() -- move to previous result row.";
910
911static PyObject *
912pgsource_moveprev(pgsourceobject *self, PyObject *args)
913{
914        return pgsource_move(self, args, QUERY_MOVEPREV);
915}
916
917/* finds field number from string/integer (internal use only) */
918static int
919pgsource_fieldindex(pgsourceobject *self, PyObject *param, const char *usage)
920{
921        int                     num;
922
923        /* checks validity */
924        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
925                return -1;
926
927        /* gets field number */
928        if (PyString_Check(param))
929                num = PQfnumber(self->result, PyString_AsString(param));
930        else if (PyInt_Check(param))
931                num = PyInt_AsLong(param);
932        else
933        {
934                PyErr_SetString(PyExc_TypeError, usage);
935                return -1;
936        }
937
938        /* checks field validity */
939        if (num < 0 || num >= self->num_fields)
940        {
941                PyErr_SetString(PyExc_ValueError, "Unknown field.");
942                return -1;
943        }
944
945        return num;
946}
947
948/* builds field information from position (internal use only) */
949static PyObject *
950pgsource_buildinfo(pgsourceobject *self, int num)
951{
952        PyObject *result;
953
954        /* allocates tuple */
955        result = PyTuple_New(3);
956        if (!result)
957                return NULL;
958
959        /* affects field information */
960        PyTuple_SET_ITEM(result, 0, PyInt_FromLong(num));
961        PyTuple_SET_ITEM(result, 1,
962                PyString_FromString(PQfname(self->result, num)));
963        PyTuple_SET_ITEM(result, 2,
964                PyInt_FromLong(PQftype(self->result, num)));
965
966        return result;
967}
968
969/* lists fields info */
970static char pgsource_listinfo__doc__[] =
971"listinfo() -- return information for all fields "
972"(position, name, type oid).";
973
974static PyObject *
975pgsource_listinfo(pgsourceobject *self, PyObject *args)
976{
977        int                     i;
978        PyObject   *result,
979                           *info;
980
981        /* checks validity */
982        if (!check_source_obj(self, CHECK_RESULT | CHECK_DQL))
983                return NULL;
984
985        /* gets args */
986        if (!PyArg_ParseTuple(args, ""))
987        {
988                PyErr_SetString(PyExc_TypeError,
989                        "method listinfo() takes no parameter.");
990                return NULL;
991        }
992
993        /* builds result */
994        if (!(result = PyTuple_New(self->num_fields)))
995                return NULL;
996
997        for (i = 0; i < self->num_fields; i++)
998        {
999                info = pgsource_buildinfo(self, i);
1000                if (!info)
1001                {
1002                        Py_DECREF(result);
1003                        return NULL;
1004                }
1005                PyTuple_SET_ITEM(result, i, info);
1006        }
1007
1008        /* returns result */
1009        return result;
1010};
1011
1012/* list fields information for last result */
1013static char pgsource_fieldinfo__doc__[] =
1014"fieldinfo(string|integer) -- return specified field information "
1015"(position, name, type oid).";
1016
1017static PyObject *
1018pgsource_fieldinfo(pgsourceobject *self, PyObject *args)
1019{
1020        static const char short_usage[] =
1021        "fieldinfo(desc), with desc (string|integer).";
1022        int                     num;
1023        PyObject   *param;
1024
1025        /* gets args */
1026        if (!PyArg_ParseTuple(args, "O", &param))
1027        {
1028                PyErr_SetString(PyExc_TypeError, short_usage);
1029                return NULL;
1030        }
1031
1032        /* checks args and validity */
1033        if ((num = pgsource_fieldindex(self, param, short_usage)) == -1)
1034                return NULL;
1035
1036        /* returns result */
1037        return pgsource_buildinfo(self, num);
1038};
1039
1040/* retrieve field value */
1041static char pgsource_field__doc__[] =
1042"field(string|integer) -- return specified field value.";
1043
1044static PyObject *
1045pgsource_field(pgsourceobject *self, PyObject *args)
1046{
1047        static const char short_usage[] =
1048        "field(desc), with desc (string|integer).";
1049        int                     num;
1050        PyObject   *param;
1051
1052        /* gets args */
1053        if (!PyArg_ParseTuple(args, "O", &param))
1054        {
1055                PyErr_SetString(PyExc_TypeError, short_usage);
1056                return NULL;
1057        }
1058
1059        /* checks args and validity */
1060        if ((num = pgsource_fieldindex(self, param, short_usage)) == -1)
1061                return NULL;
1062
1063        return PyString_FromString(PQgetvalue(self->result,
1064                                                                        self->current_row, num));
1065}
1066
1067/* query object methods */
1068static PyMethodDef pgsource_methods[] = {
1069        {"close", (PyCFunction) pgsource_close, METH_VARARGS,
1070                        pgsource_close__doc__},
1071        {"execute", (PyCFunction) pgsource_execute, METH_VARARGS,
1072                        pgsource_execute__doc__},
1073        {"oidstatus", (PyCFunction) pgsource_oidstatus, METH_VARARGS,
1074                        pgsource_oidstatus__doc__},
1075        {"fetch", (PyCFunction) pgsource_fetch, METH_VARARGS,
1076                        pgsource_fetch__doc__},
1077        {"movefirst", (PyCFunction) pgsource_movefirst, METH_VARARGS,
1078                        pgsource_movefirst__doc__},
1079        {"movelast", (PyCFunction) pgsource_movelast, METH_VARARGS,
1080                        pgsource_movelast__doc__},
1081        {"movenext", (PyCFunction) pgsource_movenext, METH_VARARGS,
1082                        pgsource_movenext__doc__},
1083        {"moveprev", (PyCFunction) pgsource_moveprev, METH_VARARGS,
1084                        pgsource_moveprev__doc__},
1085        {"field", (PyCFunction) pgsource_field, METH_VARARGS,
1086                        pgsource_field__doc__},
1087        {"fieldinfo", (PyCFunction) pgsource_fieldinfo, METH_VARARGS,
1088                        pgsource_fieldinfo__doc__},
1089        {"listinfo", (PyCFunction) pgsource_listinfo, METH_VARARGS,
1090                        pgsource_listinfo__doc__},
1091        {NULL, NULL}
1092};
1093
1094/* gets query object attributes */
1095static PyObject *
1096pgsource_getattr(pgsourceobject *self, char *name)
1097{
1098        /* pg connection object */
1099        if (!strcmp(name, "pgcnx"))
1100        {
1101                if (check_source_obj(self, 0))
1102                {
1103                        Py_INCREF(self->pgcnx);
1104                        return (PyObject *) (self->pgcnx);
1105                }
1106                Py_INCREF(Py_None);
1107                return Py_None;
1108        }
1109
1110        /* arraysize */
1111        if (!strcmp(name, "arraysize"))
1112                return PyInt_FromLong(self->arraysize);
1113
1114        /* resulttype */
1115        if (!strcmp(name, "resulttype"))
1116                return PyInt_FromLong(self->result_type);
1117
1118        /* ntuples */
1119        if (!strcmp(name, "ntuples"))
1120                return PyInt_FromLong(self->max_row);
1121
1122        /* nfields */
1123        if (!strcmp(name, "nfields"))
1124                return PyInt_FromLong(self->num_fields);
1125
1126        /* attributes list */
1127        if (!strcmp(name, "__members__"))
1128        {
1129                PyObject *list = PyList_New(5);
1130
1131                PyList_SET_ITEM(list, 0, PyString_FromString("pgcnx"));
1132                PyList_SET_ITEM(list, 1, PyString_FromString("arraysize"));
1133                PyList_SET_ITEM(list, 2, PyString_FromString("resulttype"));
1134                PyList_SET_ITEM(list, 3, PyString_FromString("ntuples"));
1135                PyList_SET_ITEM(list, 4, PyString_FromString("nfields"));
1136
1137                return list;
1138        }
1139
1140        /* module name */
1141        if (!strcmp(name, "__module__"))
1142                return PyString_FromString(MODULE_NAME);
1143
1144        /* class name */
1145        if (!strcmp(name, "__class__"))
1146                return PyString_FromString("pgsource");
1147
1148        /* seeks name in methods (fallback) */
1149        return Py_FindMethod(pgsource_methods, (PyObject *) self, name);
1150}
1151
1152/* sets query object attributes */
1153static int
1154pgsource_setattr(pgsourceobject *self, char *name, PyObject *v)
1155{
1156        /* arraysize */
1157        if (!strcmp(name, "arraysize"))
1158        {
1159                if (!PyInt_Check(v))
1160                {
1161                        PyErr_SetString(PyExc_TypeError, "arraysize must be integer.");
1162                        return -1;
1163                }
1164
1165                self->arraysize = PyInt_AsLong(v);
1166                return 0;
1167        }
1168
1169        /* unknown attribute */
1170        PyErr_SetString(PyExc_TypeError, "not a writable attribute.");
1171        return -1;
1172}
1173
1174static PyObject *
1175pgsource_repr(pgsourceobject *self)
1176{
1177        return PyString_FromString("<pg source object>");
1178}
1179
1180/* returns source object as string in human readable format */
1181
1182static PyObject *
1183pgsource_str(pgsourceobject *self)
1184{
1185        switch (self->result_type)
1186        {
1187                case RESULT_DQL:
1188                        return format_result(self->result);
1189                case RESULT_DDL:
1190                case RESULT_DML:
1191                        return PyString_FromString(PQcmdStatus(self->result));
1192                case RESULT_EMPTY:
1193                default:
1194                        return PyString_FromString("(empty PostgreSQL source object)");
1195        }
1196}
1197
1198/* query type definition */
1199staticforward PyTypeObject PgSourceType = {
1200        PyObject_HEAD_INIT(NULL)
1201        0,                                                              /* ob_size */
1202        "pgsourceobject",                               /* tp_name */
1203        sizeof(pgsourceobject),                 /* tp_basicsize */
1204        0,                                                              /* tp_itemsize */
1205        /* methods */
1206        (destructor) pgsource_dealloc,  /* tp_dealloc */
1207        0,                                                              /* tp_print */
1208        (getattrfunc) pgsource_getattr, /* tp_getattr */
1209        (setattrfunc) pgsource_setattr, /* tp_setattr */
1210        0,                                                              /* tp_compare */
1211        (reprfunc) pgsource_repr,               /* tp_repr */
1212        0,                                                              /* tp_as_number */
1213        0,                                                              /* tp_as_sequence */
1214        0,                                                              /* tp_as_mapping */
1215        0,                                                              /* tp_hash */
1216        0,                                                              /* tp_call */
1217        (reprfunc) pgsource_str,                /* tp_str */
1218};
1219
1220/* --------------------------------------------------------------------- */
1221/* PG "LARGE" OBJECT IMPLEMENTATION */
1222
1223#ifdef LARGE_OBJECTS
1224
1225/* constructor (internal use only) */
1226static pglargeobject *
1227pglarge_new(pgobject *pgcnx, Oid oid)
1228{
1229        pglargeobject *npglo;
1230
1231        if (!(npglo = PyObject_NEW(pglargeobject, &PglargeType)))
1232                return NULL;
1233
1234        Py_XINCREF(pgcnx);
1235        npglo->pgcnx = pgcnx;
1236        npglo->lo_fd = -1;
1237        npglo->lo_oid = oid;
1238
1239        return npglo;
1240}
1241
1242/* destructor */
1243static void
1244pglarge_dealloc(pglargeobject *self)
1245{
1246        if (self->lo_fd >= 0 && self->pgcnx->valid)
1247                lo_close(self->pgcnx->cnx, self->lo_fd);
1248
1249        Py_XDECREF(self->pgcnx);
1250        PyObject_Del(self);
1251}
1252
1253/* opens large object */
1254static char pglarge_open__doc__[] =
1255"open(mode) -- open access to large object with specified mode "
1256"(INV_READ, INV_WRITE constants defined by module).";
1257
1258static PyObject *
1259pglarge_open(pglargeobject *self, PyObject *args)
1260{
1261        int                     mode,
1262                                fd;
1263
1264        /* gets arguments */
1265        if (!PyArg_ParseTuple(args, "i", &mode))
1266        {
1267                PyErr_SetString(PyExc_TypeError, "open(mode), with mode(integer).");
1268                return NULL;
1269        }
1270
1271        /* check validity */
1272        if (!check_lo_obj(self, CHECK_CLOSE))
1273                return NULL;
1274
1275        /* opens large object */
1276        if ((fd = lo_open(self->pgcnx->cnx, self->lo_oid, mode)) < 0)
1277        {
1278                PyErr_SetString(PyExc_IOError, "can't open large object.");
1279                return NULL;
1280        }
1281        self->lo_fd = fd;
1282
1283        /* no error : returns Py_None */
1284        Py_INCREF(Py_None);
1285        return Py_None;
1286}
1287
1288/* close large object */
1289static char pglarge_close__doc__[] =
1290"close() -- close access to large object data.";
1291
1292static PyObject *
1293pglarge_close(pglargeobject *self, PyObject *args)
1294{
1295        /* checks args */
1296        if (!PyArg_ParseTuple(args, ""))
1297        {
1298                PyErr_SetString(PyExc_TypeError,
1299                        "method close() takes no parameters.");
1300                return NULL;
1301        }
1302
1303        /* checks validity */
1304        if (!check_lo_obj(self, CHECK_OPEN))
1305                return NULL;
1306
1307        /* closes large object */
1308        if (lo_close(self->pgcnx->cnx, self->lo_fd))
1309        {
1310                PyErr_SetString(PyExc_IOError, "error while closing large object fd.");
1311                return NULL;
1312        }
1313        self->lo_fd = -1;
1314
1315        /* no error : returns Py_None */
1316        Py_INCREF(Py_None);
1317        return Py_None;
1318}
1319
1320/* reads from large object */
1321static char pglarge_read__doc__[] =
1322"read(integer) -- read from large object to sized string. "
1323"Object must be opened in read mode before calling this method.";
1324
1325static PyObject *
1326pglarge_read(pglargeobject *self, PyObject *args)
1327{
1328        int                     size;
1329        PyObject   *buffer;
1330
1331        /* gets arguments */
1332        if (!PyArg_ParseTuple(args, "i", &size))
1333        {
1334                PyErr_SetString(PyExc_TypeError, "read(size), with size (integer).");
1335                return NULL;
1336        }
1337
1338        if (size <= 0)
1339        {
1340                PyErr_SetString(PyExc_ValueError, "size must be positive.");
1341                return NULL;
1342        }
1343
1344        /* checks validity */
1345        if (!check_lo_obj(self, CHECK_OPEN))
1346                return NULL;
1347
1348        /* allocate buffer and runs read */
1349        buffer = PyString_FromStringAndSize((char *) NULL, size);
1350
1351        if ((size = lo_read(self->pgcnx->cnx, self->lo_fd, BUF(buffer), size)) < 0)
1352        {
1353                PyErr_SetString(PyExc_IOError, "error while reading.");
1354                Py_XDECREF(buffer);
1355                return NULL;
1356        }
1357
1358        /* resize buffer and returns it */
1359        _PyString_Resize(&buffer, size);
1360        return buffer;
1361}
1362
1363/* write to large object */
1364static char pglarge_write__doc__[] =
1365"write(string) -- write sized string to large object. "
1366"Object must be opened in read mode before calling this method.";
1367
1368static PyObject *
1369pglarge_write(pglargeobject *self, PyObject *args)
1370{
1371        char       *buffer;
1372        int                     size,
1373                                bufsize;
1374
1375        /* gets arguments */
1376        if (!PyArg_ParseTuple(args, "s#", &buffer, &bufsize))
1377        {
1378                PyErr_SetString(PyExc_TypeError,
1379                        "write(buffer), with buffer (sized string).");
1380                return NULL;
1381        }
1382
1383        /* checks validity */
1384        if (!check_lo_obj(self, CHECK_OPEN))
1385                return NULL;
1386
1387        /* sends query */
1388        if ((size = lo_write(self->pgcnx->cnx, self->lo_fd, buffer,
1389                                                 bufsize)) < bufsize)
1390        {
1391                PyErr_SetString(PyExc_IOError, "buffer truncated during write.");
1392                return NULL;
1393        }
1394
1395        /* no error : returns Py_None */
1396        Py_INCREF(Py_None);
1397        return Py_None;
1398}
1399
1400/* go to position in large object */
1401static char pglarge_seek__doc__[] =
1402"seek(off, whence) -- move to specified position. Object must be opened "
1403"before calling this method. whence can be SEEK_SET, SEEK_CUR or SEEK_END, "
1404"constants defined by module.";
1405
1406static PyObject *
1407pglarge_lseek(pglargeobject *self, PyObject *args)
1408{
1409        /* offset and whence are initialized to keep compiler happy */
1410        int                     ret,
1411                                offset = 0,
1412                                whence = 0;
1413
1414        /* gets arguments */
1415        if (!PyArg_ParseTuple(args, "ii", &offset, &whence))
1416        {
1417                PyErr_SetString(PyExc_TypeError,
1418                        "lseek(offset, whence), with offset and whence (integers).");
1419                return NULL;
1420        }
1421
1422        /* checks validity */
1423        if (!check_lo_obj(self, CHECK_OPEN))
1424                return NULL;
1425
1426        /* sends query */
1427        if ((ret = lo_lseek(self->pgcnx->cnx, self->lo_fd, offset, whence)) == -1)
1428        {
1429                PyErr_SetString(PyExc_IOError, "error while moving cursor.");
1430                return NULL;
1431        }
1432
1433        /* returns position */
1434        return PyInt_FromLong(ret);
1435}
1436
1437/* gets large object size */
1438static char pglarge_size__doc__[] =
1439"size() -- return large object size. "
1440"Object must be opened before calling this method.";
1441
1442static PyObject *
1443pglarge_size(pglargeobject *self, PyObject *args)
1444{
1445        int                     start,
1446                                end;
1447
1448        /* checks args */
1449        if (!PyArg_ParseTuple(args, ""))
1450        {
1451                PyErr_SetString(PyExc_TypeError,
1452                        "method size() takes no parameters.");
1453                return NULL;
1454        }
1455
1456        /* checks validity */
1457        if (!check_lo_obj(self, CHECK_OPEN))
1458                return NULL;
1459
1460        /* gets current position */
1461        if ((start = lo_tell(self->pgcnx->cnx, self->lo_fd)) == -1)
1462        {
1463                PyErr_SetString(PyExc_IOError, "error while getting current position.");
1464                return NULL;
1465        }
1466
1467        /* gets end position */
1468        if ((end = lo_lseek(self->pgcnx->cnx, self->lo_fd, 0, SEEK_END)) == -1)
1469        {
1470                PyErr_SetString(PyExc_IOError, "error while getting end position.");
1471                return NULL;
1472        }
1473
1474        /* move back to start position */
1475        if ((start = lo_lseek(self->pgcnx->cnx, self->lo_fd, start, SEEK_SET)) == -1)
1476        {
1477                PyErr_SetString(PyExc_IOError,
1478                        "error while moving back to first position.");
1479                return NULL;
1480        }
1481
1482        /* returns size */
1483        return PyInt_FromLong(end);
1484}
1485
1486/* gets large object cursor position */
1487static char pglarge_tell__doc__[] =
1488"tell() -- give current position in large object. "
1489"Object must be opened before calling this method.";
1490
1491static PyObject *
1492pglarge_tell(pglargeobject *self, PyObject *args)
1493{
1494        int                     start;
1495
1496        /* checks args */
1497        if (!PyArg_ParseTuple(args, ""))
1498        {
1499                PyErr_SetString(PyExc_TypeError,
1500                        "method tell() takes no parameters.");
1501                return NULL;
1502        }
1503
1504        /* checks validity */
1505        if (!check_lo_obj(self, CHECK_OPEN))
1506                return NULL;
1507
1508        /* gets current position */
1509        if ((start = lo_tell(self->pgcnx->cnx, self->lo_fd)) == -1)
1510        {
1511                PyErr_SetString(PyExc_IOError, "error while getting position.");
1512                return NULL;
1513        }
1514
1515        /* returns size */
1516        return PyInt_FromLong(start);
1517}
1518
1519/* exports large object as unix file */
1520static char pglarge_export__doc__[] =
1521"export(string) -- export large object data to specified file. "
1522"Object must be closed when calling this method.";
1523
1524static PyObject *
1525pglarge_export(pglargeobject *self, PyObject *args)
1526{
1527        char *name;
1528
1529        /* checks validity */
1530        if (!check_lo_obj(self, CHECK_CLOSE))
1531                return NULL;
1532
1533        /* gets arguments */
1534        if (!PyArg_ParseTuple(args, "s", &name))
1535        {
1536                PyErr_SetString(PyExc_TypeError,
1537                        "export(filename), with filename (string).");
1538                return NULL;
1539        }
1540
1541        /* runs command */
1542        if (!lo_export(self->pgcnx->cnx, self->lo_oid, name))
1543        {
1544                PyErr_SetString(PyExc_IOError, "error while exporting large object.");
1545                return NULL;
1546        }
1547
1548        Py_INCREF(Py_None);
1549        return Py_None;
1550}
1551
1552/* deletes a large object */
1553static char pglarge_unlink__doc__[] =
1554"unlink() -- destroy large object. "
1555"Object must be closed when calling this method.";
1556
1557static PyObject *
1558pglarge_unlink(pglargeobject *self, PyObject *args)
1559{
1560        /* checks args */
1561        if (!PyArg_ParseTuple(args, ""))
1562        {
1563                PyErr_SetString(PyExc_TypeError,
1564                        "method unlink() takes no parameters.");
1565                return NULL;
1566        }
1567
1568        /* checks validity */
1569        if (!check_lo_obj(self, CHECK_CLOSE))
1570                return NULL;
1571
1572        /* deletes the object, invalidate it on success */
1573        if (!lo_unlink(self->pgcnx->cnx, self->lo_oid))
1574        {
1575                PyErr_SetString(PyExc_IOError, "error while unlinking large object");
1576                return NULL;
1577        }
1578        self->lo_oid = 0;
1579
1580        Py_INCREF(Py_None);
1581        return Py_None;
1582}
1583
1584
1585/* large object methods */
1586static struct PyMethodDef pglarge_methods[] = {
1587        {"open", (PyCFunction) pglarge_open, METH_VARARGS, pglarge_open__doc__},
1588        {"close", (PyCFunction) pglarge_close, METH_VARARGS, pglarge_close__doc__},
1589        {"read", (PyCFunction) pglarge_read, METH_VARARGS, pglarge_read__doc__},
1590        {"write", (PyCFunction) pglarge_write, METH_VARARGS, pglarge_write__doc__},
1591        {"seek", (PyCFunction) pglarge_lseek, METH_VARARGS, pglarge_seek__doc__},
1592        {"size", (PyCFunction) pglarge_size, METH_VARARGS, pglarge_size__doc__},
1593        {"tell", (PyCFunction) pglarge_tell, METH_VARARGS, pglarge_tell__doc__},
1594        {"export",(PyCFunction) pglarge_export,METH_VARARGS,pglarge_export__doc__},
1595        {"unlink",(PyCFunction) pglarge_unlink,METH_VARARGS,pglarge_unlink__doc__},
1596        {NULL, NULL}
1597};
1598
1599/* get attribute */
1600static PyObject *
1601pglarge_getattr(pglargeobject *self, char *name)
1602{
1603        /* list postgreSQL large object fields */
1604
1605        /* associated pg connection object */
1606        if (!strcmp(name, "pgcnx"))
1607        {
1608                if (check_lo_obj(self, 0))
1609                {
1610                        Py_INCREF(self->pgcnx);
1611                        return (PyObject *) (self->pgcnx);
1612                }
1613                PyErr_Clear();
1614                Py_INCREF(Py_None);
1615                return Py_None;
1616        }
1617
1618        /* large object oid */
1619        if (!strcmp(name, "oid"))
1620        {
1621                if (check_lo_obj(self, 0))
1622                        return PyInt_FromLong(self->lo_oid);
1623                PyErr_Clear();
1624                Py_INCREF(Py_None);
1625                return Py_None;
1626        }
1627
1628        /* error (status) message */
1629        if (!strcmp(name, "error"))
1630                return PyString_FromString(PQerrorMessage(self->pgcnx->cnx));
1631
1632        /* attributes list */
1633        if (!strcmp(name, "__members__"))
1634        {
1635                PyObject *list = PyList_New(3);
1636
1637                if (list)
1638                {
1639                        PyList_SET_ITEM(list, 0, PyString_FromString("oid"));
1640                        PyList_SET_ITEM(list, 1, PyString_FromString("pgcnx"));
1641                        PyList_SET_ITEM(list, 2, PyString_FromString("error"));
1642                }
1643
1644                return list;
1645        }
1646
1647        /* module name */
1648        if (!strcmp(name, "__module__"))
1649                return PyString_FromString(MODULE_NAME);
1650
1651        /* class name */
1652        if (!strcmp(name, "__class__"))
1653                return PyString_FromString("pglarge");
1654
1655        /* seeks name in methods (fallback) */
1656        return Py_FindMethod(pglarge_methods, (PyObject *) self, name);
1657}
1658
1659/* prints query object in human readable format */
1660static int
1661pglarge_print(pglargeobject *self, FILE *fp, int flags)
1662{
1663        char            print_buffer[128];
1664        PyOS_snprintf(print_buffer, sizeof(print_buffer),
1665                self->lo_fd >= 0 ?
1666                        "Opened large object, oid %ld" :
1667                        "Closed large object, oid %ld", (long) self->lo_oid);
1668        fputs(print_buffer, fp);
1669        return 0;
1670}
1671
1672/* object type definition */
1673staticforward PyTypeObject PglargeType = {
1674        PyObject_HEAD_INIT(NULL)
1675        0,                                                      /* ob_size */
1676        "pglarge",                                      /* tp_name */
1677        sizeof(pglargeobject),          /* tp_basicsize */
1678        0,                                                      /* tp_itemsize */
1679
1680        /* methods */
1681        (destructor) pglarge_dealloc,           /* tp_dealloc */
1682        (printfunc) pglarge_print,      /* tp_print */
1683        (getattrfunc) pglarge_getattr,          /* tp_getattr */
1684        0,                                                      /* tp_setattr */
1685        0,                                                      /* tp_compare */
1686        0,                                                      /* tp_repr */
1687        0,                                                      /* tp_as_number */
1688        0,                                                      /* tp_as_sequence */
1689        0,                                                      /* tp_as_mapping */
1690        0,                                                      /* tp_hash */
1691};
1692#endif /* LARGE_OBJECTS */
1693
1694
1695/* --------------------------------------------------------------------- */
1696/* PG QUERY OBJECT IMPLEMENTATION */
1697
1698/* connects to a database */
1699static char connect__doc__[] =
1700"connect(dbname, host, port, opt, tty) -- connect to a PostgreSQL database "
1701"using specified parameters (optionals, keywords aware).";
1702
1703static PyObject *
1704pgconnect(pgobject *self, PyObject *args, PyObject *dict)
1705{
1706        static const char *kwlist[] = {"dbname", "host", "port", "opt",
1707        "tty", "user", "passwd", NULL};
1708
1709        char       *pghost,
1710                           *pgopt,
1711                           *pgtty,
1712                           *pgdbname,
1713                           *pguser,
1714                           *pgpasswd;
1715        int                     pgport;
1716        char            port_buffer[20];
1717        pgobject   *npgobj;
1718
1719        pghost = pgopt = pgtty = pgdbname = pguser = pgpasswd = NULL;
1720        pgport = -1;
1721
1722        /*
1723         * parses standard arguments With the right compiler warnings, this
1724         * will issue a diagnostic. There is really no way around it.  If I
1725         * don't declare kwlist as const char *kwlist[] then it complains when
1726         * I try to assign all those constant strings to it.
1727         */
1728        if (!PyArg_ParseTupleAndKeywords(args, dict, "|zzizzzz", (char **) kwlist,
1729                &pgdbname, &pghost, &pgport, &pgopt, &pgtty, &pguser, &pgpasswd))
1730                return NULL;
1731
1732#ifdef DEFAULT_VARS
1733        /* handles defaults variables (for uninitialised vars) */
1734        if ((!pghost) && (pg_default_host != Py_None))
1735                pghost = PyString_AsString(pg_default_host);
1736
1737        if ((pgport == -1) && (pg_default_port != Py_None))
1738                pgport = PyInt_AsLong(pg_default_port);
1739
1740        if ((!pgopt) && (pg_default_opt != Py_None))
1741                pgopt = PyString_AsString(pg_default_opt);
1742
1743        if ((!pgtty) && (pg_default_tty != Py_None))
1744                pgtty = PyString_AsString(pg_default_tty);
1745
1746        if ((!pgdbname) && (pg_default_base != Py_None))
1747                pgdbname = PyString_AsString(pg_default_base);
1748
1749        if ((!pguser) && (pg_default_user != Py_None))
1750                pguser = PyString_AsString(pg_default_user);
1751
1752        if ((!pgpasswd) && (pg_default_passwd != Py_None))
1753                pgpasswd = PyString_AsString(pg_default_passwd);
1754#endif /* DEFAULT_VARS */
1755
1756        if (!(npgobj = (pgobject *) pgobject_New()))
1757                return NULL;
1758
1759        if (pgport != -1)
1760        {
1761                memset(port_buffer, 0, sizeof(port_buffer));
1762                sprintf(port_buffer, "%d", pgport);
1763        }
1764
1765#ifdef PQsetdbLoginIsThreadSafe
1766        Py_BEGIN_ALLOW_THREADS
1767#endif
1768        npgobj->cnx = PQsetdbLogin(pghost, pgport == -1 ? NULL : port_buffer,
1769                pgopt, pgtty, pgdbname, pguser, pgpasswd);
1770#ifdef PQsetdbLoginIsThreadSafe
1771        Py_END_ALLOW_THREADS
1772#endif
1773
1774        if (PQstatus(npgobj->cnx) == CONNECTION_BAD)
1775        {
1776                set_dberror(InternalError, PQerrorMessage(npgobj->cnx), NULL);
1777                Py_XDECREF(npgobj);
1778                return NULL;
1779        }
1780
1781        return (PyObject *) npgobj;
1782}
1783
1784/* internal wrapper for the notice receiver callback */
1785void notice_receiver(void *arg, const PGresult *res)
1786{
1787        PyGILState_STATE gstate = PyGILState_Ensure();
1788        pgobject *self = (pgobject*) arg;
1789        PyObject *proc = self->notice_receiver;
1790
1791        if (proc && PyCallable_Check(proc))
1792        {
1793                pgnoticeobject *notice = PyObject_NEW(pgnoticeobject, &PgNoticeType);
1794                PyObject *ret;
1795                if (notice)
1796                {
1797                        notice->pgcnx = arg;
1798                        notice->res = res;
1799                }
1800                else
1801                {
1802                        Py_INCREF(Py_None);
1803                        notice = (pgnoticeobject *)(void *)Py_None;
1804                }
1805                ret = PyObject_CallFunction(proc, "(O)", notice);
1806                Py_XDECREF(ret);
1807        }
1808        PyGILState_Release(gstate);
1809}
1810
1811/* pgobject methods */
1812
1813/* destructor */
1814static void
1815pg_dealloc(pgobject *self)
1816{
1817        if (self->cnx)
1818        {
1819                Py_BEGIN_ALLOW_THREADS
1820                PQfinish(self->cnx);
1821                Py_END_ALLOW_THREADS
1822        }
1823        if (self->notice_receiver)
1824        {
1825                Py_DECREF(self->notice_receiver);
1826        }
1827        PyObject_Del(self);
1828}
1829
1830/* close without deleting */
1831static char pg_close__doc__[] =
1832"close() -- close connection. All instances of the connection object and "
1833"derived objects (queries and large objects) can no longer be used after "
1834"this call.";
1835
1836static PyObject *
1837pg_close(pgobject *self, PyObject *args)
1838{
1839        /* gets args */
1840        if (!PyArg_ParseTuple(args, ""))
1841        {
1842                PyErr_SetString(PyExc_TypeError, "close().");
1843                return NULL;
1844        }
1845
1846        /* connection object cannot already be closed */
1847        if (!self->cnx)
1848        {
1849                set_dberror(InternalError, "Connection already closed", NULL);
1850                return NULL;
1851        }
1852
1853        Py_BEGIN_ALLOW_THREADS
1854        PQfinish(self->cnx);
1855        Py_END_ALLOW_THREADS
1856
1857        self->cnx = NULL;
1858        Py_INCREF(Py_None);
1859        return Py_None;
1860}
1861
1862static void
1863pgquery_dealloc(pgqueryobject *self)
1864{
1865        if (self->result)
1866                PQclear(self->result);
1867
1868        PyObject_Del(self);
1869}
1870
1871/* resets connection */
1872static char pg_reset__doc__[] =
1873"reset() -- reset connection with current parameters. All derived queries "
1874"and large objects derived from this connection will not be usable after "
1875"this call.";
1876
1877static PyObject *
1878pg_reset(pgobject *self, PyObject *args)
1879{
1880        if (!self->cnx)
1881        {
1882                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
1883                return NULL;
1884        }
1885
1886        /* checks args */
1887        if (!PyArg_ParseTuple(args, ""))
1888        {
1889                PyErr_SetString(PyExc_TypeError,
1890                        "method reset() takes no parameters.");
1891                return NULL;
1892        }
1893
1894        /* resets the connection */
1895        PQreset(self->cnx);
1896        Py_INCREF(Py_None);
1897        return Py_None;
1898}
1899
1900/* cancels current command */
1901static char pg_cancel__doc__[] =
1902"cancel() -- abandon processing of the current command.";
1903
1904static PyObject *
1905pg_cancel(pgobject *self, PyObject *args)
1906{
1907        if (!self->cnx)
1908        {
1909                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
1910                return NULL;
1911        }
1912
1913        /* checks args */
1914        if (!PyArg_ParseTuple(args, ""))
1915        {
1916                PyErr_SetString(PyExc_TypeError,
1917                        "method cancel() takes no parameters.");
1918                return NULL;
1919        }
1920
1921        /* request that the server abandon processing of the current command */
1922        return PyInt_FromLong((long) PQrequestCancel(self->cnx));
1923}
1924
1925/* get connection socket */
1926static char pg_fileno__doc__[] =
1927"fileno() -- return database connection socket file handle.";
1928
1929static PyObject *
1930pg_fileno(pgobject *self, PyObject *args)
1931{
1932        if (!self->cnx)
1933        {
1934                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
1935                return NULL;
1936        }
1937
1938        /* checks args */
1939        if (!PyArg_ParseTuple(args, ""))
1940        {
1941                PyErr_SetString(PyExc_TypeError,
1942                        "method fileno() takes no parameters.");
1943                return NULL;
1944        }
1945
1946#ifdef NO_PQSOCKET
1947        return PyInt_FromLong((long) self->cnx->sock);
1948#else
1949        return PyInt_FromLong((long) PQsocket(self->cnx));
1950#endif
1951}
1952
1953/* set notice receiver callback function */
1954static char pg_set_notice_receiver__doc__[] =
1955"set_notice_receiver() -- set the current notice receiver.";
1956
1957static PyObject *
1958pg_set_notice_receiver(pgobject * self, PyObject * args)
1959{
1960        PyObject *ret = NULL;
1961        PyObject *proc;
1962
1963        if (PyArg_ParseTuple(args, "O", &proc))
1964        {
1965                if (proc == Py_None)
1966                {
1967                        Py_XDECREF(self->notice_receiver);
1968                        self->notice_receiver = NULL;
1969                        Py_INCREF(Py_None); ret = Py_None;
1970                }
1971                else if (PyCallable_Check(proc))
1972                {
1973                        Py_XINCREF(proc); Py_XDECREF(self->notice_receiver);
1974                        self->notice_receiver = proc;
1975                        PQsetNoticeReceiver(self->cnx, notice_receiver, self);
1976                        Py_INCREF(Py_None); ret = Py_None;
1977                }
1978                else
1979                        PyErr_SetString(PyExc_TypeError, "notice receiver must be callable");
1980        }
1981        return ret;
1982}
1983
1984/* get notice receiver callback function */
1985static char pg_get_notice_receiver__doc__[] =
1986"get_notice_receiver() -- get the current notice receiver.";
1987
1988static PyObject *
1989pg_get_notice_receiver(pgobject * self, PyObject * args)
1990{
1991        PyObject *ret = NULL;
1992
1993        if (PyArg_ParseTuple(args, ""))
1994        {
1995                ret = self->notice_receiver;
1996                if (!ret)
1997                        ret = Py_None;
1998                Py_INCREF(ret);
1999        }
2000        else
2001        {
2002                PyErr_SetString(PyExc_TypeError,
2003                        "method get_notice_receiver() takes no parameters.");
2004        }
2005        return ret;
2006}
2007
2008/* get number of rows */
2009static char pgquery_ntuples__doc__[] =
2010"ntuples() -- returns number of tuples returned by query.";
2011
2012static PyObject *
2013pgquery_ntuples(pgqueryobject *self, PyObject *args)
2014{
2015        /* checks args */
2016        if (!PyArg_ParseTuple(args, ""))
2017        {
2018                PyErr_SetString(PyExc_TypeError,
2019                        "method ntuples() takes no parameters.");
2020                return NULL;
2021        }
2022
2023        return PyInt_FromLong((long) PQntuples(self->result));
2024}
2025
2026/* list fields names from query result */
2027static char pgquery_listfields__doc__[] =
2028"listfields() -- Lists field names from result.";
2029
2030static PyObject *
2031pgquery_listfields(pgqueryobject *self, PyObject *args)
2032{
2033        int                     i,
2034                                n;
2035        char       *name;
2036        PyObject   *fieldstuple,
2037                           *str;
2038
2039        /* checks args */
2040        if (!PyArg_ParseTuple(args, ""))
2041        {
2042                PyErr_SetString(PyExc_TypeError,
2043                        "method listfields() takes no parameters.");
2044                return NULL;
2045        }
2046
2047        /* builds tuple */
2048        n = PQnfields(self->result);
2049        fieldstuple = PyTuple_New(n);
2050
2051        for (i = 0; i < n; i++)
2052        {
2053                name = PQfname(self->result, i);
2054                str = PyString_FromString(name);
2055                PyTuple_SET_ITEM(fieldstuple, i, str);
2056        }
2057
2058        return fieldstuple;
2059}
2060
2061/* get field name from last result */
2062static char pgquery_fieldname__doc__[] =
2063"fieldname() -- returns name of field from result from its position.";
2064
2065static PyObject *
2066pgquery_fieldname(pgqueryobject *self, PyObject *args)
2067{
2068        int             i;
2069        char   *name;
2070
2071        /* gets args */
2072        if (!PyArg_ParseTuple(args, "i", &i))
2073        {
2074                PyErr_SetString(PyExc_TypeError,
2075                        "fieldname(number), with number(integer).");
2076                return NULL;
2077        }
2078
2079        /* checks number validity */
2080        if (i >= PQnfields(self->result))
2081        {
2082                PyErr_SetString(PyExc_ValueError, "invalid field number.");
2083                return NULL;
2084        }
2085
2086        /* gets fields name and builds object */
2087        name = PQfname(self->result, i);
2088        return PyString_FromString(name);
2089}
2090
2091/* gets fields number from name in last result */
2092static char pgquery_fieldnum__doc__[] =
2093"fieldnum() -- returns position in query for field from its name.";
2094
2095static PyObject *
2096pgquery_fieldnum(pgqueryobject *self, PyObject *args)
2097{
2098        int             num;
2099        char   *name;
2100
2101        /* gets args */
2102        if (!PyArg_ParseTuple(args, "s", &name))
2103        {
2104                PyErr_SetString(PyExc_TypeError, "fieldnum(name), with name (string).");
2105                return NULL;
2106        }
2107
2108        /* gets field number */
2109        if ((num = PQfnumber(self->result, name)) == -1)
2110        {
2111                PyErr_SetString(PyExc_ValueError, "Unknown field.");
2112                return NULL;
2113        }
2114
2115        return PyInt_FromLong(num);
2116}
2117
2118/* retrieves last result */
2119static char pgquery_getresult__doc__[] =
2120"getresult() -- Gets the result of a query.  The result is returned "
2121"as a list of rows, each one a tuple of fields in the order returned "
2122"by the server.";
2123
2124static PyObject *
2125pgquery_getresult(pgqueryobject *self, PyObject *args)
2126{
2127        PyObject   *rowtuple,
2128                           *reslist,
2129                           *val;
2130        int                     i,
2131                                j,
2132                                m,
2133                                n,
2134                           *typ;
2135
2136        /* checks args (args == NULL for an internal call) */
2137        if (args && !PyArg_ParseTuple(args, ""))
2138        {
2139                PyErr_SetString(PyExc_TypeError,
2140                        "method getresult() takes no parameters.");
2141                return NULL;
2142        }
2143
2144        /* stores result in tuple */
2145        m = PQntuples(self->result);
2146        n = PQnfields(self->result);
2147        reslist = PyList_New(m);
2148
2149        typ = get_type_array(self->result, n);
2150
2151        for (i = 0; i < m; i++)
2152        {
2153                if (!(rowtuple = PyTuple_New(n)))
2154                {
2155                        Py_DECREF(reslist);
2156                        reslist = NULL;
2157                        goto exit;
2158                }
2159
2160                for (j = 0; j < n; j++)
2161                {
2162                        int                     k;
2163                        char       *s = PQgetvalue(self->result, i, j);
2164                        char            cashbuf[64];
2165                        PyObject   *tmp_obj;
2166
2167                        if (PQgetisnull(self->result, i, j))
2168                        {
2169                                Py_INCREF(Py_None);
2170                                val = Py_None;
2171                        }
2172                        else
2173                                switch (typ[j])
2174                                {
2175                                        case PYGRES_INT:
2176                                                val = PyInt_FromString(s, NULL, 10);
2177                                                break;
2178
2179                                        case PYGRES_LONG:
2180                                                val = PyLong_FromString(s, NULL, 10);
2181                                                break;
2182
2183                                        case PYGRES_FLOAT:
2184                                                tmp_obj = PyString_FromString(s);
2185                                                val = PyFloat_FromString(tmp_obj, NULL);
2186                                                Py_DECREF(tmp_obj);
2187                                                break;
2188
2189                                        case PYGRES_MONEY:
2190                                                /* convert to decimal only if decimal point is set */
2191                                                if (!decimal_point) goto default_case;
2192                                                for (k = 0;
2193                                                         *s && k < sizeof(cashbuf) / sizeof(cashbuf[0]) - 1;
2194                                                         s++)
2195                                                {
2196                                                        if (*s >= '0' && *s <= '9')
2197                                                                cashbuf[k++] = *s;
2198                                                        else if (*s == decimal_point)
2199                                                                cashbuf[k++] = '.';
2200                                                        else if (*s == '(' || *s == '-')
2201                                                                cashbuf[k++] = '-';
2202                                                }
2203                                                cashbuf[k] = 0;
2204                                                s = cashbuf;
2205                                                /* FALLTHROUGH */ /* no break */
2206
2207                                        case PYGRES_DECIMAL:
2208                                                if (decimal)
2209                                                {
2210                                                        val = PyObject_CallFunction(decimal, "(s)", s);
2211                                                }
2212                                                else
2213                                                {
2214                                                        tmp_obj = PyString_FromString(s);
2215                                                        val = PyFloat_FromString(tmp_obj, NULL);
2216                                                        Py_DECREF(tmp_obj);
2217                                                }
2218                                                break;
2219
2220                                        case PYGRES_BOOL:
2221                                                /* convert to bool only if bool_type is set */
2222                                                if (use_bool)
2223                                                {
2224                                                        val = *s == 't' ? Py_True : Py_False;
2225                                                        Py_INCREF(val);
2226                                                        break;
2227                                                }
2228                                                /* FALLTHROUGH */ /* no break */
2229
2230                                        default:
2231                                        default_case:
2232                                                val = PyString_FromString(s);
2233                                                break;
2234                                }
2235
2236                        if (!val)
2237                        {
2238                                Py_DECREF(reslist);
2239                                Py_DECREF(rowtuple);
2240                                reslist = NULL;
2241                                goto exit;
2242                        }
2243
2244                        PyTuple_SET_ITEM(rowtuple, j, val);
2245                }
2246
2247                PyList_SET_ITEM(reslist, i, rowtuple);
2248        }
2249
2250exit:
2251        PyMem_Free(typ);
2252
2253        /* returns list */
2254        return reslist;
2255}
2256
2257/* retrieves last result as a list of dictionaries*/
2258static char pgquery_dictresult__doc__[] =
2259"dictresult() -- Gets the result of a query.  The result is returned "
2260"as a list of rows, each one a dictionary with the field names used "
2261"as the labels.";
2262
2263static PyObject *
2264pgquery_dictresult(pgqueryobject *self, PyObject *args)
2265{
2266        PyObject   *dict,
2267                           *reslist,
2268                           *val;
2269        int                     i,
2270                                j,
2271                                m,
2272                                n,
2273                           *typ;
2274
2275        /* checks args (args == NULL for an internal call) */
2276        if (args && !PyArg_ParseTuple(args, ""))
2277        {
2278                PyErr_SetString(PyExc_TypeError,
2279                        "method dictresult() takes no parameters.");
2280                return NULL;
2281        }
2282
2283        /* stores result in list */
2284        m = PQntuples(self->result);
2285        n = PQnfields(self->result);
2286        reslist = PyList_New(m);
2287
2288        typ = get_type_array(self->result, n);
2289
2290        for (i = 0; i < m; i++)
2291        {
2292                if (!(dict = PyDict_New()))
2293                {
2294                        Py_DECREF(reslist);
2295                        reslist = NULL;
2296                        goto exit;
2297                }
2298
2299                for (j = 0; j < n; j++)
2300                {
2301                        int                     k;
2302                        char       *s = PQgetvalue(self->result, i, j);
2303                        char            cashbuf[64];
2304                        PyObject   *tmp_obj;
2305
2306                        if (PQgetisnull(self->result, i, j))
2307                        {
2308                                Py_INCREF(Py_None);
2309                                val = Py_None;
2310                        }
2311                        else
2312                                switch (typ[j])
2313                                {
2314                                        case PYGRES_INT:
2315                                                val = PyInt_FromString(s, NULL, 10);
2316                                                break;
2317
2318                                        case PYGRES_LONG:
2319                                                val = PyLong_FromString(s, NULL, 10);
2320                                                break;
2321
2322                                        case PYGRES_FLOAT:
2323                                                tmp_obj = PyString_FromString(s);
2324                                                val = PyFloat_FromString(tmp_obj, NULL);
2325                                                Py_DECREF(tmp_obj);
2326                                                break;
2327
2328                                        case PYGRES_MONEY:
2329                                                /* convert to decimal only if decimal point is set */
2330                                                if (!decimal_point) goto default_case;
2331
2332                                                for (k = 0;
2333                                                         *s && k < sizeof(cashbuf) / sizeof(cashbuf[0]) - 1;
2334                                                         s++)
2335                                                {
2336                                                        if (*s >= '0' && *s <= '9')
2337                                                                cashbuf[k++] = *s;
2338                                                        else if (*s == decimal_point)
2339                                                                cashbuf[k++] = '.';
2340                                                        else if (*s == '(' || *s == '-')
2341                                                                cashbuf[k++] = '-';
2342                                                }
2343                                                cashbuf[k] = 0;
2344                                                s = cashbuf;
2345                                                /* FALLTHROUGH */ /* no break */
2346
2347                                        case PYGRES_DECIMAL:
2348                                                if (decimal)
2349                                                {
2350                                                        val = PyObject_CallFunction(decimal, "(s)", s);
2351                                                }
2352                                                else
2353                                                {
2354                                                        tmp_obj = PyString_FromString(s);
2355                                                        val = PyFloat_FromString(tmp_obj, NULL);
2356                                                        Py_DECREF(tmp_obj);
2357                                                }
2358                                                break;
2359
2360                                        case PYGRES_BOOL:
2361                                                /* convert to bool only if bool_type is set */
2362                                                if (use_bool)
2363                                                {
2364                                                        val = *s == 't' ? Py_True : Py_False;
2365                                                        Py_INCREF(val);
2366                                                        break;
2367                                                }
2368                                                /* FALLTHROUGH */ /* no break */
2369
2370                                        default:
2371                                        default_case:
2372                                                val = PyString_FromString(s);
2373                                                break;
2374                                }
2375
2376                        if (!val)
2377                        {
2378                                Py_DECREF(dict);
2379                                Py_DECREF(reslist);
2380                                reslist = NULL;
2381                                goto exit;
2382                        }
2383
2384                        PyDict_SetItemString(dict, PQfname(self->result, j), val);
2385                        Py_DECREF(val);
2386                }
2387
2388                PyList_SET_ITEM(reslist, i, dict);
2389        }
2390
2391exit:
2392        PyMem_Free(typ);
2393
2394        /* returns list */
2395        return reslist;
2396}
2397
2398/* retrieves last result as named tuples */
2399static char pgquery_namedresult__doc__[] =
2400"namedresult() -- Gets the result of a query.  The result is returned "
2401"as a list of rows, each one a tuple of fields in the order returned "
2402"by the server.";
2403
2404static PyObject *
2405pgquery_namedresult(pgqueryobject *self, PyObject *args)
2406{
2407        PyObject   *ret;
2408
2409        /* checks args (args == NULL for an internal call) */
2410        if (args && !PyArg_ParseTuple(args, ""))
2411        {
2412                PyErr_SetString(PyExc_TypeError,
2413                        "method namedresult() takes no parameters.");
2414                return NULL;
2415        }
2416
2417        if (!namedresult)
2418        {
2419                PyErr_SetString(PyExc_TypeError,
2420                        "named tuples are not supported.");
2421                return NULL;
2422        }
2423
2424        ret = PyObject_CallFunction(namedresult, "(O)", self);
2425
2426        if (ret == NULL)
2427            return NULL;
2428
2429        return ret;
2430}
2431
2432/* gets asynchronous notify */
2433static char pg_getnotify__doc__[] =
2434"getnotify() -- get database notify for this connection.";
2435
2436static PyObject *
2437pg_getnotify(pgobject *self, PyObject *args)
2438{
2439        PGnotify   *notify;
2440
2441        if (!self->cnx)
2442        {
2443                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
2444                return NULL;
2445        }
2446
2447        /* checks args */
2448        if (!PyArg_ParseTuple(args, ""))
2449        {
2450                PyErr_SetString(PyExc_TypeError,
2451                        "method getnotify() takes no parameters.");
2452                return NULL;
2453        }
2454
2455        /* checks for NOTIFY messages */
2456        PQconsumeInput(self->cnx);
2457
2458        if (!(notify = PQnotifies(self->cnx)))
2459        {
2460                Py_INCREF(Py_None);
2461                return Py_None;
2462        }
2463        else
2464        {
2465                PyObject   *notify_result,
2466                                   *temp;
2467
2468                if (!(temp = PyString_FromString(notify->relname)))
2469                        return NULL;
2470
2471                if (!(notify_result = PyTuple_New(3)))
2472                        return NULL;
2473
2474                PyTuple_SET_ITEM(notify_result, 0, temp);
2475
2476                if (!(temp = PyInt_FromLong(notify->be_pid)))
2477                {
2478                        Py_DECREF(notify_result);
2479                        return NULL;
2480                }
2481
2482                PyTuple_SET_ITEM(notify_result, 1, temp);
2483
2484                /* extra exists even in old versions that did not support it */
2485                if (!(temp = PyString_FromString(notify->extra)))
2486                {
2487                        Py_DECREF(notify_result);
2488                        return NULL;
2489                }
2490
2491                PyTuple_SET_ITEM(notify_result, 2, temp);
2492
2493                PQfreemem(notify);
2494
2495                return notify_result;
2496        }
2497}
2498
2499/* source creation */
2500static char pg_source__doc__[] =
2501"source() -- creates a new source object for this connection";
2502
2503static PyObject *
2504pg_source(pgobject *self, PyObject *args)
2505{
2506        /* checks validity */
2507        if (!check_cnx_obj(self))
2508                return NULL;
2509
2510        /* checks args */
2511        if (!PyArg_ParseTuple(args, ""))
2512        {
2513                PyErr_SetString(PyExc_TypeError, "method source() takes no parameter.");
2514                return NULL;
2515        }
2516
2517        /* allocate new pg query object */
2518        return (PyObject *) pgsource_new(self);
2519}
2520
2521/* database query */
2522static char pg_query__doc__[] =
2523"query(sql, [args]) -- creates a new query object for this connection, using"
2524" sql (string) request and optionally a tuple with positional parameters.";
2525
2526static PyObject *
2527pg_query(pgobject *self, PyObject *args)
2528{
2529        char            *query;
2530        PyObject        *param_obj = NULL;
2531        PGresult        *result;
2532        pgqueryobject *npgobj;
2533        int                     status,
2534                                nparms = 0;
2535
2536        if (!self->cnx)
2537        {
2538                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
2539                return NULL;
2540        }
2541
2542        /* get query args */
2543        if (!PyArg_ParseTuple(args, "s|O", &query, &param_obj))
2544        {
2545                PyErr_SetString(PyExc_TypeError, "query(sql, [args]), with sql (string).");
2546                return NULL;
2547        }
2548
2549        /* If param_obj is passed, ensure it's a non-empty tuple. We want to treat
2550         * an empty tuple the same as no argument since we'll get that when the
2551         * caller passes no arguments to db.query(), and historic behaviour was
2552         * to call PQexec() in that case, which can execute multiple commands. */
2553        if (param_obj)
2554        {
2555                param_obj = PySequence_Fast(param_obj,
2556                        "query parameters must be a sequence.");
2557                if (!param_obj)
2558                        return NULL;
2559                nparms = (int)PySequence_Fast_GET_SIZE(param_obj);
2560
2561                /* if there's a single argument and it's a list or tuple, it
2562                 * contains the positional arguments. */
2563                if (nparms == 1)
2564                {
2565                        PyObject *first_obj = PySequence_Fast_GET_ITEM(param_obj, 0);
2566                        if (PyList_Check(first_obj) || PyTuple_Check(first_obj))
2567                        {
2568                                Py_DECREF(param_obj);
2569                                param_obj = PySequence_Fast(first_obj, NULL);
2570                                nparms = (int)PySequence_Fast_GET_SIZE(param_obj);
2571                        }
2572                }
2573        }
2574
2575        /* gets result */
2576        if (nparms)
2577        {
2578                /* prepare arguments */
2579                PyObject        **str, **s;
2580                char            **parms, **p, *enc=NULL;
2581                register int i;
2582
2583                str = (PyObject **)PyMem_Malloc(nparms * sizeof(*str));
2584                parms = (char **)PyMem_Malloc(nparms * sizeof(*parms));
2585                if (!str || !parms) {
2586                        PyMem_Free(parms);
2587                        PyMem_Free(str);
2588                        Py_XDECREF(param_obj);
2589                        PyErr_SetString(PyExc_MemoryError, "memory error in query().");
2590                        return NULL;
2591                }
2592
2593                /* convert optional args to a list of strings -- this allows
2594                 * the caller to pass whatever they like, and prevents us
2595                 * from having to map types to OIDs */
2596                for (i = 0, s=str, p=parms; i < nparms; i++, p++)
2597                {
2598                        PyObject *obj = PySequence_Fast_GET_ITEM(param_obj, i);
2599
2600                        if (obj == Py_None)
2601                        {
2602                                *p = NULL;
2603                        }
2604                        else if (PyUnicode_Check(obj))
2605                        {
2606                                PyObject *str_obj;
2607                                if (!enc)
2608                                        enc = (char *)pg_encoding_to_char(
2609                                                PQclientEncoding(self->cnx));
2610                                if (!strcmp(enc, "UTF8"))
2611                                        str_obj = PyUnicode_AsUTF8String(obj);
2612                                else if (!strcmp(enc, "LATIN1"))
2613                                        str_obj = PyUnicode_AsLatin1String(obj);
2614                                else if (!strcmp(enc, "SQL_ASCII"))
2615                                        str_obj = PyUnicode_AsASCIIString(obj);
2616                                else
2617                                        str_obj = PyUnicode_AsEncodedString(obj, enc, "strict");
2618                                if (!str_obj)
2619                                {
2620                                        PyMem_Free(parms);
2621                                        while (s != str) { s--; Py_DECREF(*s); }
2622                                        PyMem_Free(str);
2623                                        Py_XDECREF(param_obj);
2624                                        PyErr_SetString(PyExc_UnicodeError, "query parameter"
2625                                                " could not be decoded (bad client encoding)");
2626                                        return NULL;
2627                                }
2628                                *s++ = str_obj;
2629                                *p = PyString_AsString(str_obj);
2630                        }
2631                        else
2632                        {
2633                                PyObject *str_obj = PyObject_Str(obj);
2634                                if (!str_obj)
2635                                {
2636                                        PyMem_Free(parms);
2637                                        while (s != str) { s--; Py_DECREF(*s); }
2638                                        PyMem_Free(str);
2639                                        Py_XDECREF(param_obj);
2640                                        PyErr_SetString(PyExc_TypeError,
2641                                                "query parameter has no string representation");
2642                                        return NULL;
2643                                }
2644                                *s++ = str_obj;
2645                                *p = PyString_AsString(str_obj);
2646                        }
2647                }
2648
2649                Py_BEGIN_ALLOW_THREADS
2650                result = PQexecParams(self->cnx, query, nparms,
2651                        NULL, (const char * const *)parms, NULL, NULL, 0);
2652                Py_END_ALLOW_THREADS
2653
2654                PyMem_Free(parms);
2655                while (s != str) { s--; Py_DECREF(*s); }
2656                PyMem_Free(str);
2657        }
2658        else
2659        {
2660                Py_BEGIN_ALLOW_THREADS
2661                result = PQexec(self->cnx, query);
2662                Py_END_ALLOW_THREADS
2663        }
2664
2665        /* we don't need the params any more */
2666        Py_XDECREF(param_obj);
2667
2668        /* checks result validity */
2669        if (!result)
2670        {
2671                PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
2672                return NULL;
2673        }
2674
2675        /* checks result status */
2676        if ((status = PQresultStatus(result)) != PGRES_TUPLES_OK)
2677        {
2678                switch (status)
2679                {
2680                        case PGRES_EMPTY_QUERY:
2681                                PyErr_SetString(PyExc_ValueError, "empty query.");
2682                                break;
2683                        case PGRES_BAD_RESPONSE:
2684                        case PGRES_FATAL_ERROR:
2685                        case PGRES_NONFATAL_ERROR:
2686                                set_dberror(ProgrammingError,
2687                                        PQerrorMessage(self->cnx), result);
2688                                break;
2689                        case PGRES_COMMAND_OK:
2690                                {                                               /* INSERT, UPDATE, DELETE */
2691                                        Oid             oid = PQoidValue(result);
2692                                        if (oid == InvalidOid)  /* not a single insert */
2693                                        {
2694                                                char    *ret = PQcmdTuples(result);
2695
2696                                                if (ret[0])             /* return number of rows affected */
2697                                                {
2698                                                        PyObject *obj = PyString_FromString(ret);
2699                                                        PQclear(result);
2700                                                        return obj;
2701                                                }
2702                                                PQclear(result);
2703                                                Py_INCREF(Py_None);
2704                                                return Py_None;
2705                                        }
2706                                        /* for a single insert, return the oid */
2707                                        PQclear(result);
2708                                        return PyInt_FromLong(oid);
2709                                }
2710                        case PGRES_COPY_OUT:            /* no data will be received */
2711                        case PGRES_COPY_IN:
2712                                PQclear(result);
2713                                Py_INCREF(Py_None);
2714                                return Py_None;
2715                        default:
2716                                set_dberror(InternalError,
2717                                        "internal error: unknown result status.", result);
2718                                break;
2719                }
2720
2721                PQclear(result);
2722                return NULL;                    /* error detected on query */
2723        }
2724
2725        if (!(npgobj = PyObject_NEW(pgqueryobject, &PgQueryType)))
2726                return NULL;
2727
2728        /* stores result and returns object */
2729        npgobj->result = result;
2730        return (PyObject *) npgobj;
2731}
2732
2733#ifdef DIRECT_ACCESS
2734static char pg_putline__doc__[] =
2735"putline() -- sends a line directly to the backend";
2736
2737/* direct acces function : putline */
2738static PyObject *
2739pg_putline(pgobject *self, PyObject *args)
2740{
2741        char *line;
2742
2743        if (!self->cnx)
2744        {
2745                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
2746                return NULL;
2747        }
2748
2749        /* reads args */
2750        if (!PyArg_ParseTuple(args, "s", &line))
2751        {
2752                PyErr_SetString(PyExc_TypeError, "putline(line), with line (string).");
2753                return NULL;
2754        }
2755
2756        /* sends line to backend */
2757        if (PQputline(self->cnx, line))
2758        {
2759                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2760                return NULL;
2761        }
2762        Py_INCREF(Py_None);
2763        return Py_None;
2764}
2765
2766/* direct access function : getline */
2767static char pg_getline__doc__[] =
2768"getline() -- gets a line directly from the backend.";
2769
2770static PyObject *
2771pg_getline(pgobject *self, PyObject *args)
2772{
2773        char            line[MAX_BUFFER_SIZE];
2774        PyObject   *str = NULL;         /* GCC */
2775
2776        if (!self->cnx)
2777        {
2778                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
2779                return NULL;
2780        }
2781
2782        /* checks args */
2783        if (!PyArg_ParseTuple(args, ""))
2784        {
2785                PyErr_SetString(PyExc_TypeError,
2786                        "method getline() takes no parameters.");
2787                return NULL;
2788        }
2789
2790        /* gets line */
2791        switch (PQgetline(self->cnx, line, MAX_BUFFER_SIZE))
2792        {
2793                case 0:
2794                        str = PyString_FromString(line);
2795                        break;
2796                case 1:
2797                        PyErr_SetString(PyExc_MemoryError, "buffer overflow");
2798                        str = NULL;
2799                        break;
2800                case EOF:
2801                        Py_INCREF(Py_None);
2802                        str = Py_None;
2803                        break;
2804        }
2805
2806        return str;
2807}
2808
2809/* direct access function : end copy */
2810static char pg_endcopy__doc__[] =
2811"endcopy() -- synchronizes client and server";
2812
2813static PyObject *
2814pg_endcopy(pgobject *self, PyObject *args)
2815{
2816        if (!self->cnx)
2817        {
2818                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
2819                return NULL;
2820        }
2821
2822        /* checks args */
2823        if (!PyArg_ParseTuple(args, ""))
2824        {
2825                PyErr_SetString(PyExc_TypeError,
2826                        "method endcopy() takes no parameters.");
2827                return NULL;
2828        }
2829
2830        /* ends direct copy */
2831        if (PQendcopy(self->cnx))
2832        {
2833                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
2834                return NULL;
2835        }
2836        Py_INCREF(Py_None);
2837        return Py_None;
2838}
2839#endif /* DIRECT_ACCESS */
2840
2841static PyObject *
2842pgquery_repr(pgqueryobject *self)
2843{
2844        return PyString_FromString("<pg query result>");
2845}
2846
2847static PyObject *
2848pgquery_str(pgqueryobject *self)
2849{
2850        return format_result(self->result);
2851}
2852
2853/* insert table */
2854static char pg_inserttable__doc__[] =
2855"inserttable(string, list) -- insert list in table. The fields in the "
2856"list must be in the same order as in the table.";
2857
2858static PyObject *
2859pg_inserttable(pgobject *self, PyObject *args)
2860{
2861        PGresult        *result;
2862        char            *table,
2863                                *buffer,
2864                                *bufpt;
2865        size_t          bufsiz;
2866        PyObject        *list,
2867                                *sublist,
2868                                *item;
2869        PyObject        *(*getitem) (PyObject *, Py_ssize_t);
2870        PyObject        *(*getsubitem) (PyObject *, Py_ssize_t);
2871        Py_ssize_t      i,
2872                                j,
2873                                m,
2874                                n;
2875
2876        if (!self->cnx)
2877        {
2878                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
2879                return NULL;
2880        }
2881
2882        /* gets arguments */
2883        if (!PyArg_ParseTuple(args, "sO:filter", &table, &list))
2884        {
2885                PyErr_SetString(PyExc_TypeError,
2886                        "inserttable(table, content), with table (string) "
2887                        "and content (list).");
2888                return NULL;
2889        }
2890
2891        /* checks list type */
2892        if (PyTuple_Check(list))
2893        {
2894                m = PyTuple_Size(list);
2895                getitem = PyTuple_GetItem;
2896        }
2897        else if (PyList_Check(list))
2898        {
2899                m = PyList_Size(list);
2900                getitem = PyList_GetItem;
2901        }
2902        else
2903        {
2904                PyErr_SetString(PyExc_TypeError,
2905                        "second arg must be some kind of array.");
2906                return NULL;
2907        }
2908
2909        /* allocate buffer */
2910        if (!(buffer = PyMem_Malloc(MAX_BUFFER_SIZE)))
2911        {
2912                PyErr_SetString(PyExc_MemoryError,
2913                        "can't allocate insert buffer.");
2914                return NULL;
2915        }
2916
2917        /* starts query */
2918        sprintf(buffer, "copy %s from stdin", table);
2919
2920        Py_BEGIN_ALLOW_THREADS
2921        result = PQexec(self->cnx, buffer);
2922        Py_END_ALLOW_THREADS
2923
2924        if (!result)
2925        {
2926                PyMem_Free(buffer);
2927                PyErr_SetString(PyExc_ValueError, PQerrorMessage(self->cnx));
2928                return NULL;
2929        }
2930
2931        PQclear(result);
2932
2933        n = 0; /* not strictly necessary but avoids warning */
2934
2935        /* feed table */
2936        for (i = 0; i < m; i++)
2937        {
2938                sublist = getitem(list, i);
2939                if (PyTuple_Check(sublist))
2940                {
2941                        j = PyTuple_Size(sublist);
2942                        getsubitem = PyTuple_GetItem;
2943                }
2944                else if (PyList_Check(sublist))
2945                {
2946                        j = PyList_Size(sublist);
2947                        getsubitem = PyList_GetItem;
2948                }
2949                else
2950                {
2951                        PyErr_SetString(PyExc_TypeError,
2952                                "second arg must contain some kind of arrays.");
2953                        return NULL;
2954                }
2955                if (i)
2956                {
2957                        if (j != n)
2958                        {
2959                                PyMem_Free(buffer);
2960                                PyErr_SetString(PyExc_TypeError,
2961                                        "arrays contained in second arg must have same size.");
2962                                return NULL;
2963                        }
2964                }
2965                else
2966                {
2967                        n = j; /* never used before this assignment */
2968                }
2969
2970                /* builds insert line */
2971                bufpt = buffer;
2972                bufsiz = MAX_BUFFER_SIZE - 1;
2973
2974                for (j = 0; j < n; j++)
2975                {
2976                        if (j)
2977                        {
2978                                *bufpt++ = '\t'; --bufsiz;
2979                        }
2980
2981                        item = getsubitem(sublist, j);
2982
2983                        /* convert item to string and append to buffer */
2984                        if (item == Py_None)
2985                        {
2986                                if (bufsiz > 2)
2987                                {
2988                                        *bufpt++ = '\\'; *bufpt++ = 'N';
2989                                        bufsiz -= 2;
2990                                }
2991                                else
2992                                        bufsiz = 0;
2993                        }
2994                        else if (PyString_Check(item))
2995                        {
2996                                const char* t = PyString_AS_STRING(item);
2997                                while (*t && bufsiz)
2998                                {
2999                                        if (*t == '\\' || *t == '\t' || *t == '\n')
3000                                        {
3001                                                *bufpt++ = '\\'; --bufsiz;
3002                                                if (!bufsiz) break;
3003                                        }
3004                                        *bufpt++ = *t++; --bufsiz;
3005                                }
3006                        }
3007                        else if (PyInt_Check(item) || PyLong_Check(item))
3008                        {
3009                                PyObject* s = PyObject_Str(item);
3010                                const char* t = PyString_AsString(s);
3011                                while (*t && bufsiz)
3012                                {
3013                                        *bufpt++ = *t++; --bufsiz;
3014                                }
3015                                Py_DECREF(s);
3016                        }
3017                        else
3018                        {
3019                                PyObject* s = PyObject_Repr(item);
3020                                const char* t = PyString_AsString(s);
3021                                while (*t && bufsiz)
3022                                {
3023                                        if (*t == '\\' || *t == '\t' || *t == '\n')
3024                                        {
3025                                                *bufpt++ = '\\'; --bufsiz;
3026                                                if (!bufsiz) break;
3027                                        }
3028                                        *bufpt++ = *t++; --bufsiz;
3029                                }
3030                                Py_DECREF(s);
3031                        }
3032
3033                        if (bufsiz <= 0)
3034                        {
3035                                PyMem_Free(buffer);
3036                                PyErr_SetString(PyExc_MemoryError,
3037                                        "insert buffer overflow.");
3038                                return NULL;
3039                        }
3040
3041                }
3042
3043                *bufpt++ = '\n'; *bufpt = '\0';
3044
3045                /* sends data */
3046                if (PQputline(self->cnx, buffer))
3047                {
3048                        PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
3049                        PQendcopy(self->cnx);
3050                        PyMem_Free(buffer);
3051                        return NULL;
3052                }
3053        }
3054
3055        /* ends query */
3056        if (PQputline(self->cnx, "\\.\n"))
3057        {
3058                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
3059                PQendcopy(self->cnx);
3060                PyMem_Free(buffer);
3061                return NULL;
3062        }
3063
3064        if (PQendcopy(self->cnx))
3065        {
3066                PyErr_SetString(PyExc_IOError, PQerrorMessage(self->cnx));
3067                PyMem_Free(buffer);
3068                return NULL;
3069        }
3070
3071        PyMem_Free(buffer);
3072
3073        /* no error : returns nothing */
3074        Py_INCREF(Py_None);
3075        return Py_None;
3076}
3077
3078/* get transaction state */
3079static char pg_transaction__doc__[] =
3080"Returns the current transaction status.";
3081
3082static PyObject *
3083pg_transaction(pgobject *self, PyObject *args)
3084{
3085        if (!self->cnx)
3086        {
3087                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
3088                return NULL;
3089        }
3090
3091        /* checks args */
3092        if (!PyArg_ParseTuple(args, ""))
3093        {
3094                PyErr_SetString(PyExc_TypeError,
3095                        "method transaction() takes no parameters.");
3096                return NULL;
3097        }
3098
3099        return PyInt_FromLong(PQtransactionStatus(self->cnx));
3100}
3101
3102/* get parameter setting */
3103static char pg_parameter__doc__[] =
3104"Looks up a current parameter setting.";
3105
3106static PyObject *
3107pg_parameter(pgobject *self, PyObject *args)
3108{
3109        const char *name;
3110
3111        if (!self->cnx)
3112        {
3113                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
3114                return NULL;
3115        }
3116
3117        /* get query args */
3118        if (!PyArg_ParseTuple(args, "s", &name))
3119        {
3120                PyErr_SetString(PyExc_TypeError, "parameter(name), with name (string).");
3121                return NULL;
3122        }
3123
3124        name = PQparameterStatus(self->cnx, name);
3125
3126        if (name)
3127                return PyString_FromString(name);
3128
3129        /* unknown parameter, return None */
3130        Py_INCREF(Py_None);
3131        return Py_None;
3132}
3133
3134#ifdef ESCAPING_FUNCS
3135
3136/* escape literal */
3137static char pg_escape_literal__doc__[] =
3138"pg_escape_literal(str) -- escape a literal constant for use within SQL.";
3139
3140static PyObject *
3141pg_escape_literal(pgobject *self, PyObject *args)
3142{
3143        char *str; /* our string argument */
3144        int str_length; /* length of string */
3145        char *esc; /* the escaped version of the string */
3146        PyObject *ret; /* string object to return */
3147
3148        if (!PyArg_ParseTuple(args, "s#", &str, &str_length))
3149                return NULL;
3150        esc = PQescapeLiteral(self->cnx, str, (size_t)str_length);
3151        ret = Py_BuildValue("s", esc);
3152        if (esc)
3153                PQfreemem(esc);
3154        if (!ret) /* pass on exception */
3155                return NULL;
3156        return ret;
3157}
3158
3159/* escape identifier */
3160static char pg_escape_identifier__doc__[] =
3161"pg_escape_identifier(str) -- escape an identifier for use within SQL.";
3162
3163static PyObject *
3164pg_escape_identifier(pgobject *self, PyObject *args)
3165{
3166        char *str; /* our string argument */
3167        int str_length; /* length of string */
3168        char *esc; /* the escaped version of the string */
3169        PyObject *ret; /* string object to return */
3170
3171        if (!PyArg_ParseTuple(args, "s#", &str, &str_length))
3172                return NULL;
3173        esc = PQescapeIdentifier(self->cnx, str, (size_t)str_length);
3174        ret = Py_BuildValue("s", esc);
3175        if (esc)
3176                PQfreemem(esc);
3177        if (!ret) /* pass on exception */
3178                return NULL;
3179        return ret;
3180}
3181
3182#endif  /* ESCAPING_FUNCS */
3183
3184/* escape string */
3185static char pg_escape_string__doc__[] =
3186"pg_escape_string(str) -- escape a string for use within SQL.";
3187
3188static PyObject *
3189pg_escape_string(pgobject *self, PyObject *args)
3190{
3191        char *from; /* our string argument */
3192        char *to=NULL; /* the result */
3193        int from_length; /* length of string */
3194        int to_length; /* length of result */
3195        PyObject *ret; /* string object to return */
3196
3197        if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
3198                return NULL;
3199        to_length = 2*from_length + 1;
3200        if (to_length < from_length) /* overflow */
3201        {
3202                to_length = from_length;
3203                from_length = (from_length - 1)/2;
3204        }
3205        to = (char *)PyMem_Malloc(to_length);
3206        to_length = (int)PQescapeStringConn(self->cnx,
3207                to, from, (size_t)from_length, NULL);
3208        ret = Py_BuildValue("s#", to, to_length);
3209        PyMem_Free(to);
3210        if (!ret) /* pass on exception */
3211                return NULL;
3212        return ret;
3213}
3214
3215/* escape bytea */
3216static char pg_escape_bytea__doc__[] =
3217"pg_escape_bytea(data) -- escape binary data for use within SQL as type bytea.";
3218
3219static PyObject *
3220pg_escape_bytea(pgobject *self, PyObject *args)
3221{
3222        unsigned char *from; /* our string argument */
3223        unsigned char *to; /* the result */
3224        int from_length; /* length of string */
3225        size_t to_length; /* length of result */
3226        PyObject *ret; /* string object to return */
3227
3228        if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
3229                return NULL;
3230        to = PQescapeByteaConn(self->cnx, from, (int)from_length, &to_length);
3231        ret = Py_BuildValue("s", to);
3232        if (to)
3233                PQfreemem((void *)to);
3234        if (!ret) /* pass on exception */
3235                return NULL;
3236        return ret;
3237}
3238
3239#ifdef LARGE_OBJECTS
3240/* creates large object */
3241static char pg_locreate__doc__[] =
3242"locreate() -- creates a new large object in the database.";
3243
3244static PyObject *
3245pg_locreate(pgobject *self, PyObject *args)
3246{
3247        int                     mode;
3248        Oid                     lo_oid;
3249
3250        /* checks validity */
3251        if (!check_cnx_obj(self))
3252                return NULL;
3253
3254        /* gets arguments */
3255        if (!PyArg_ParseTuple(args, "i", &mode))
3256        {
3257                PyErr_SetString(PyExc_TypeError,
3258                        "locreate(mode), with mode (integer).");
3259                return NULL;
3260        }
3261
3262        /* creates large object */
3263        lo_oid = lo_creat(self->cnx, mode);
3264        if (lo_oid == 0)
3265        {
3266                set_dberror(OperationalError, "can't create large object.", NULL);
3267                return NULL;
3268        }
3269
3270        return (PyObject *) pglarge_new(self, lo_oid);
3271}
3272
3273/* init from already known oid */
3274static char pg_getlo__doc__[] =
3275"getlo(long) -- create a large object instance for the specified oid.";
3276
3277static PyObject *
3278pg_getlo(pgobject *self, PyObject *args)
3279{
3280        int                     lo_oid;
3281
3282        /* checks validity */
3283        if (!check_cnx_obj(self))
3284                return NULL;
3285
3286        /* gets arguments */
3287        if (!PyArg_ParseTuple(args, "i", &lo_oid))
3288        {
3289                PyErr_SetString(PyExc_TypeError, "getlo(oid), with oid (integer).");
3290                return NULL;
3291        }
3292
3293        if (!lo_oid)
3294        {
3295                PyErr_SetString(PyExc_ValueError, "the object oid can't be null.");
3296                return NULL;
3297        }
3298
3299        /* creates object */
3300        return (PyObject *) pglarge_new(self, lo_oid);
3301}
3302
3303/* import unix file */
3304static char pg_loimport__doc__[] =
3305"loimport(string) -- create a new large object from specified file.";
3306
3307static PyObject *
3308pg_loimport(pgobject *self, PyObject *args)
3309{
3310        char   *name;
3311        Oid             lo_oid;
3312
3313        /* checks validity */
3314        if (!check_cnx_obj(self))
3315                return NULL;
3316
3317        /* gets arguments */
3318        if (!PyArg_ParseTuple(args, "s", &name))
3319        {
3320                PyErr_SetString(PyExc_TypeError, "loimport(name), with name (string).");
3321                return NULL;
3322        }
3323
3324        /* imports file and checks result */
3325        lo_oid = lo_import(self->cnx, name);
3326        if (lo_oid == 0)
3327        {
3328                set_dberror(OperationalError, "can't create large object.", NULL);
3329                return NULL;
3330        }
3331
3332        return (PyObject *) pglarge_new(self, lo_oid);
3333}
3334#endif /* LARGE_OBJECTS */
3335
3336
3337/* connection object methods */
3338static struct PyMethodDef pgobj_methods[] = {
3339        {"source", (PyCFunction) pg_source, METH_VARARGS, pg_source__doc__},
3340        {"query", (PyCFunction) pg_query, METH_VARARGS, pg_query__doc__},
3341        {"reset", (PyCFunction) pg_reset, METH_VARARGS, pg_reset__doc__},
3342        {"cancel", (PyCFunction) pg_cancel, METH_VARARGS, pg_cancel__doc__},
3343        {"close", (PyCFunction) pg_close, METH_VARARGS, pg_close__doc__},
3344        {"fileno", (PyCFunction) pg_fileno, METH_VARARGS, pg_fileno__doc__},
3345        {"get_notice_receiver", (PyCFunction) pg_get_notice_receiver, METH_VARARGS,
3346                        pg_get_notice_receiver__doc__},
3347        {"set_notice_receiver", (PyCFunction) pg_set_notice_receiver, METH_VARARGS,
3348                        pg_set_notice_receiver__doc__},
3349        {"getnotify", (PyCFunction) pg_getnotify, METH_VARARGS,
3350                        pg_getnotify__doc__},
3351        {"inserttable", (PyCFunction) pg_inserttable, METH_VARARGS,
3352                        pg_inserttable__doc__},
3353        {"transaction", (PyCFunction) pg_transaction, METH_VARARGS,
3354                        pg_transaction__doc__},
3355        {"parameter", (PyCFunction) pg_parameter, METH_VARARGS,
3356                        pg_parameter__doc__},
3357
3358#ifdef ESCAPING_FUNCS
3359        {"escape_literal", (PyCFunction) pg_escape_literal, METH_VARARGS,
3360                        pg_escape_literal__doc__},
3361        {"escape_identifier", (PyCFunction) pg_escape_identifier, METH_VARARGS,
3362                        pg_escape_identifier__doc__},
3363#endif  /* ESCAPING_FUNCS */
3364        {"escape_string", (PyCFunction) pg_escape_string, METH_VARARGS,
3365                        pg_escape_string__doc__},
3366        {"escape_bytea", (PyCFunction) pg_escape_bytea, METH_VARARGS,
3367                        pg_escape_bytea__doc__},
3368
3369#ifdef DIRECT_ACCESS
3370        {"putline", (PyCFunction) pg_putline, 1, pg_putline__doc__},
3371        {"getline", (PyCFunction) pg_getline, 1, pg_getline__doc__},
3372        {"endcopy", (PyCFunction) pg_endcopy, 1, pg_endcopy__doc__},
3373#endif /* DIRECT_ACCESS */
3374
3375#ifdef LARGE_OBJECTS
3376        {"locreate", (PyCFunction) pg_locreate, 1, pg_locreate__doc__},
3377        {"getlo", (PyCFunction) pg_getlo, 1, pg_getlo__doc__},
3378        {"loimport", (PyCFunction) pg_loimport, 1, pg_loimport__doc__},
3379#endif /* LARGE_OBJECTS */
3380
3381        {NULL, NULL} /* sentinel */
3382};
3383
3384/* get attribute */
3385static PyObject *
3386pg_getattr(pgobject *self, char *name)
3387{
3388        /*
3389         * Although we could check individually, there are only a few
3390         * attributes that don't require a live connection and unless someone
3391         * has an urgent need, this will have to do
3392         */
3393
3394        /* first exception - close which returns a different error */
3395        if (strcmp(name, "close") && !self->cnx)
3396        {
3397                PyErr_SetString(PyExc_TypeError, "Connection is not valid.");
3398                return NULL;
3399        }
3400
3401        /* list PostgreSQL connection fields */
3402
3403        /* postmaster host */
3404        if (!strcmp(name, "host"))
3405        {
3406                char *r = PQhost(self->cnx);
3407                if (!r)
3408                        r = "localhost";
3409                return PyString_FromString(r);
3410        }
3411
3412        /* postmaster port */
3413        if (!strcmp(name, "port"))
3414                return PyInt_FromLong(atol(PQport(self->cnx)));
3415
3416        /* selected database */
3417        if (!strcmp(name, "db"))
3418                return PyString_FromString(PQdb(self->cnx));
3419
3420        /* selected options */
3421        if (!strcmp(name, "options"))
3422                return PyString_FromString(PQoptions(self->cnx));
3423
3424        /* selected postgres tty */
3425        if (!strcmp(name, "tty"))
3426                return PyString_FromString(PQtty(self->cnx));
3427
3428        /* error (status) message */
3429        if (!strcmp(name, "error"))
3430                return PyString_FromString(PQerrorMessage(self->cnx));
3431
3432        /* connection status : 1 - OK, 0 - BAD */
3433        if (!strcmp(name, "status"))
3434                return PyInt_FromLong(PQstatus(self->cnx) == CONNECTION_OK ? 1 : 0);
3435
3436        /* provided user name */
3437        if (!strcmp(name, "user"))
3438                return PyString_FromString(PQuser(self->cnx));
3439
3440        /* protocol version */
3441        if (!strcmp(name, "protocol_version"))
3442                return PyInt_FromLong(PQprotocolVersion(self->cnx));
3443
3444        /* backend version */
3445        if (!strcmp(name, "server_version"))
3446#if PG_VERSION_NUM < 80000
3447                return PyInt_FromLong(PG_VERSION_NUM);
3448#else
3449                return PyInt_FromLong(PQserverVersion(self->cnx));
3450#endif
3451
3452        /* attributes list */
3453        if (!strcmp(name, "__members__"))
3454        {
3455                PyObject *list = PyList_New(10);
3456
3457                if (list)
3458                {
3459                        PyList_SET_ITEM(list, 0, PyString_FromString("host"));
3460                        PyList_SET_ITEM(list, 1, PyString_FromString("port"));
3461                        PyList_SET_ITEM(list, 2, PyString_FromString("db"));
3462                        PyList_SET_ITEM(list, 3, PyString_FromString("options"));
3463                        PyList_SET_ITEM(list, 4, PyString_FromString("tty"));
3464                        PyList_SET_ITEM(list, 5, PyString_FromString("error"));
3465                        PyList_SET_ITEM(list, 6, PyString_FromString("status"));
3466                        PyList_SET_ITEM(list, 7, PyString_FromString("user"));
3467                        PyList_SET_ITEM(list, 8, PyString_FromString("protocol_version"));
3468                        PyList_SET_ITEM(list, 9, PyString_FromString("server_version"));
3469                }
3470
3471                return list;
3472        }
3473
3474        return Py_FindMethod(pgobj_methods, (PyObject *) self, name);
3475}
3476
3477/* object type definition */
3478staticforward PyTypeObject PgType = {
3479        PyObject_HEAD_INIT(NULL)
3480        0,                                                      /* ob_size */
3481        "pgobject",                                     /* tp_name */
3482        sizeof(pgobject),                       /* tp_basicsize */
3483        0,                                                      /* tp_itemsize */
3484        /* methods */
3485        (destructor) pg_dealloc,        /* tp_dealloc */
3486        0,                                                      /* tp_print */
3487        (getattrfunc) pg_getattr,       /* tp_getattr */
3488        0,                                                      /* tp_setattr */
3489        0,                                                      /* tp_compare */
3490        0,                                                      /* tp_repr */
3491        0,                                                      /* tp_as_number */
3492        0,                                                      /* tp_as_sequence */
3493        0,                                                      /* tp_as_mapping */
3494        0,                                                      /* tp_hash */
3495};
3496
3497
3498/* get attribute */
3499static PyObject *
3500pgnotice_getattr(pgnoticeobject *self, char *name)
3501{
3502        PGresult const *res = self->res;
3503        int fieldcode;
3504
3505        if (!res)
3506        {
3507                PyErr_SetString(PyExc_TypeError, "Cannot get current notice.");
3508                return NULL;
3509        }
3510
3511        /* pg connection object */
3512        if (!strcmp(name, "pgcnx"))
3513        {
3514                if (self->pgcnx && check_cnx_obj(self->pgcnx))
3515                {
3516                        Py_INCREF(self->pgcnx);
3517                        return (PyObject *) self->pgcnx;
3518                }
3519                else
3520                {
3521                        Py_INCREF(Py_None);
3522                        return Py_None;
3523                }
3524        }
3525
3526        /* full message */
3527        if (!strcmp(name, "message"))
3528                return PyString_FromString(PQresultErrorMessage(res));
3529
3530        /* other possible fields */
3531        fieldcode = 0;
3532        if (!strcmp(name, "severity"))
3533                fieldcode = PG_DIAG_SEVERITY;
3534        else if (!strcmp(name, "primary"))
3535                fieldcode = PG_DIAG_MESSAGE_PRIMARY;
3536        else if (!strcmp(name, "detail"))
3537                fieldcode = PG_DIAG_MESSAGE_DETAIL;
3538        else if (!strcmp(name, "hint"))
3539                fieldcode = PG_DIAG_MESSAGE_HINT;
3540        if (fieldcode)
3541        {
3542                char *s = PQresultErrorField(res, fieldcode);
3543                if (s)
3544                        return PyString_FromString(s);
3545                else
3546                {
3547                        Py_INCREF(Py_None); return Py_None;
3548                }
3549        }
3550
3551        /* attributes list */
3552        if (!strcmp(name, "__members__"))
3553        {
3554                PyObject *list = PyList_New(6);
3555                if (list)
3556                {
3557                        PyList_SET_ITEM(list, 0, PyString_FromString("pgcnx"));
3558                        PyList_SET_ITEM(list, 1, PyString_FromString("severity"));
3559                        PyList_SET_ITEM(list, 2, PyString_FromString("message"));
3560                        PyList_SET_ITEM(list, 3, PyString_FromString("primary"));
3561                        PyList_SET_ITEM(list, 4, PyString_FromString("detail"));
3562                        PyList_SET_ITEM(list, 5, PyString_FromString("hint"));
3563                }
3564                return list;
3565        }
3566
3567        PyErr_Format(PyExc_AttributeError,
3568                "'pgnoticeobject' has no attribute %s", name);
3569        return NULL;
3570}
3571
3572static PyObject *
3573pgnotice_str(pgnoticeobject *self)
3574{
3575        return pgnotice_getattr(self, "message");
3576}
3577
3578/* object type definition */
3579staticforward PyTypeObject PgNoticeType = {
3580        PyObject_HEAD_INIT(NULL)
3581        0,                                                      /* ob_size */
3582        "pgnoticeobject",                       /* tp_name */
3583        sizeof(pgnoticeobject),         /* tp_basicsize */
3584        0,                                                      /* tp_itemsize */
3585        /* methods */
3586        0,                                                              /* tp_dealloc */
3587        0,                                                              /* tp_print */
3588        (getattrfunc) pgnotice_getattr, /* tp_getattr */
3589        0,                                                              /* tp_setattr */
3590        0,                                                              /* tp_compare */
3591        0,                                                              /* tp_repr */
3592        0,                                                              /* tp_as_number */
3593        0,                                                              /* tp_as_sequence */
3594        0,                                                              /* tp_as_mapping */
3595        0,                                                              /* tp_hash */
3596        0,                                                              /* tp_call */
3597        (reprfunc) pgnotice_str                 /* tp_str */
3598};
3599
3600
3601/* query object methods */
3602static struct PyMethodDef pgquery_methods[] = {
3603        {"getresult", (PyCFunction) pgquery_getresult, METH_VARARGS,
3604                        pgquery_getresult__doc__},
3605        {"dictresult", (PyCFunction) pgquery_dictresult, METH_VARARGS,
3606                        pgquery_dictresult__doc__},
3607        {"namedresult", (PyCFunction) pgquery_namedresult, METH_VARARGS,
3608                        pgquery_namedresult__doc__},
3609        {"fieldname", (PyCFunction) pgquery_fieldname, METH_VARARGS,
3610                         pgquery_fieldname__doc__},
3611        {"fieldnum", (PyCFunction) pgquery_fieldnum, METH_VARARGS,
3612                        pgquery_fieldnum__doc__},
3613        {"listfields", (PyCFunction) pgquery_listfields, METH_VARARGS,
3614                        pgquery_listfields__doc__},
3615        {"ntuples", (PyCFunction) pgquery_ntuples, METH_VARARGS,
3616                        pgquery_ntuples__doc__},
3617        {NULL, NULL}
3618};
3619
3620/* gets query object attributes */
3621static PyObject *
3622pgquery_getattr(pgqueryobject *self, char *name)
3623{
3624        /* list postgreSQL connection fields */
3625        return Py_FindMethod(pgquery_methods, (PyObject *) self, name);
3626}
3627
3628/* query type definition */
3629staticforward PyTypeObject PgQueryType = {
3630        PyObject_HEAD_INIT(NULL)
3631        0,                                                              /* ob_size */
3632        "pgqueryobject",                                /* tp_name */
3633        sizeof(pgqueryobject),                  /* tp_basicsize */
3634        0,                                                              /* tp_itemsize */
3635        /* methods */
3636        (destructor) pgquery_dealloc,   /* tp_dealloc */
3637        0,                                                              /* tp_print */
3638        (getattrfunc) pgquery_getattr,  /* tp_getattr */
3639        0,                                                              /* tp_setattr */
3640        0,                                                              /* tp_compare */
3641        (reprfunc) pgquery_repr,                /* tp_repr */
3642        0,                                                              /* tp_as_number */
3643        0,                                                              /* tp_as_sequence */
3644        0,                                                              /* tp_as_mapping */
3645        0,                                                              /* tp_hash */
3646        0,                                                              /* tp_call */
3647        (reprfunc) pgquery_str                  /* tp_str */
3648};
3649
3650
3651/* --------------------------------------------------------------------- */
3652
3653/* MODULE FUNCTIONS */
3654
3655/* escape string */
3656static char escape_string__doc__[] =
3657"escape_string(str) -- escape a string for use within SQL.";
3658
3659static PyObject *
3660escape_string(PyObject *self, PyObject *args)
3661{
3662        char *from; /* our string argument */
3663        char *to=NULL; /* the result */
3664        int from_length; /* length of string */
3665        int to_length; /* length of result */
3666        PyObject *ret; /* string object to return */
3667
3668        if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
3669                return NULL;
3670        to_length = 2*from_length + 1;
3671        if (to_length < from_length) /* overflow */
3672        {
3673                to_length = from_length;
3674                from_length = (from_length - 1)/2;
3675        }
3676        to = (char *)PyMem_Malloc(to_length);
3677        to_length = (int)PQescapeString(to, from, (size_t)from_length);
3678        ret = Py_BuildValue("s#", to, to_length);
3679        PyMem_Free(to);
3680        if (!ret) /* pass on exception */
3681                return NULL;
3682        return ret;
3683}
3684
3685/* escape bytea */
3686static char escape_bytea__doc__[] =
3687"escape_bytea(data) -- escape binary data for use within SQL as type bytea.";
3688
3689static PyObject *
3690escape_bytea(PyObject *self, PyObject *args)
3691{
3692        unsigned char *from; /* our string argument */
3693        unsigned char *to; /* the result */
3694        int from_length; /* length of string */
3695        size_t to_length; /* length of result */
3696        PyObject *ret; /* string object to return */
3697
3698        if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
3699                return NULL;
3700        to = PQescapeBytea(from, (int)from_length, &to_length);
3701        ret = Py_BuildValue("s", to);
3702        if (to)
3703                PQfreemem((void *)to);
3704        if (!ret) /* pass on exception */
3705                return NULL;
3706        return ret;
3707}
3708
3709/* unescape bytea */
3710static char unescape_bytea__doc__[] =
3711"unescape_bytea(str) -- unescape bytea data that has been retrieved as text.";
3712
3713static PyObject
3714*unescape_bytea(PyObject *self, PyObject *args)
3715{
3716        unsigned char *from; /* our string argument */
3717        unsigned char *to; /* the result */
3718        size_t to_length; /* length of result string */
3719        PyObject *ret; /* string object to return */
3720
3721        if (!PyArg_ParseTuple(args, "s", &from))
3722                return NULL;
3723        to = PQunescapeBytea(from, &to_length);
3724        ret = Py_BuildValue("s#", to, (int)to_length);
3725        if (to)
3726                PQfreemem((void *)to);
3727        if (!ret) /* pass on exception */
3728                return NULL;
3729        return ret;
3730}
3731
3732/* get decimal point */
3733static char get_decimal_point__doc__[] =
3734"get_decimal_point() -- get decimal point to be used for money values.";
3735
3736static PyObject *
3737get_decimal_point(PyObject *self, PyObject * args)
3738{
3739        PyObject *ret = NULL;
3740        char s[2];
3741
3742        if (PyArg_ParseTuple(args, ""))
3743        {
3744                if (decimal_point)
3745                {
3746                        s[0] = decimal_point; s[1] = '\0';
3747                        ret = PyString_FromString(s);
3748                } else {
3749                        Py_INCREF(Py_None); ret = Py_None;
3750                }
3751        }
3752        else
3753        {
3754                PyErr_SetString(PyExc_TypeError,
3755                        "get_decimal_point() takes no parameter");
3756        }
3757
3758        return ret;
3759}
3760
3761/* set decimal point */
3762static char set_decimal_point__doc__[] =
3763"set_decimal_point(char) -- set decimal point to be used for money values.";
3764
3765static PyObject *
3766set_decimal_point(PyObject *self, PyObject * args)
3767{
3768        PyObject *ret = NULL;
3769        char *s = NULL;
3770
3771        /* gets arguments */
3772        if (PyArg_ParseTuple(args, "z", &s)) {
3773                if (!s)
3774                        s = "\0";
3775                else if (*s && (*(s+1) || !strchr(".,;: '*/_`|", *s)))
3776                        s = NULL;
3777        }
3778
3779        if (s) {
3780                decimal_point = *s;
3781                Py_INCREF(Py_None); ret = Py_None;
3782        } else {
3783                PyErr_SetString(PyExc_TypeError,
3784                        "set_decimal_point() expects a decimal mark character");
3785        }
3786
3787        return ret;
3788}
3789
3790/* get decimal type */
3791static char get_decimal__doc__[] =
3792"get_decimal() -- set a decimal type to be used for numeric values.";
3793
3794static PyObject *
3795get_decimal(PyObject *self, PyObject *args)
3796{
3797        PyObject *ret = NULL;
3798
3799        if (PyArg_ParseTuple(args, ""))
3800        {
3801                ret = decimal ? decimal : Py_None;
3802                Py_INCREF(ret);
3803        }
3804
3805        return ret;
3806}
3807
3808/* set decimal type */
3809static char set_decimal__doc__[] =
3810"set_decimal(cls) -- set a decimal type to be used for numeric values.";
3811
3812static PyObject *
3813set_decimal(PyObject *self, PyObject *args)
3814{
3815        PyObject *ret = NULL;
3816        PyObject *cls;
3817
3818        if (PyArg_ParseTuple(args, "O", &cls))
3819        {
3820                if (cls == Py_None)
3821                {
3822                        Py_XDECREF(decimal); decimal = NULL;
3823                        Py_INCREF(Py_None); ret = Py_None;
3824                }
3825                else if (PyCallable_Check(cls))
3826                {
3827                        Py_XINCREF(cls); Py_XDECREF(decimal); decimal = cls;
3828                        Py_INCREF(Py_None); ret = Py_None;
3829                }
3830                else
3831                        PyErr_SetString(PyExc_TypeError,
3832                                "decimal type must be None or callable");
3833        }
3834
3835        return ret;
3836}
3837
3838/* get usage of bool values */
3839static char get_bool__doc__[] =
3840"get_bool() -- check whether boolean values are converted to bool.";
3841
3842static PyObject *
3843get_bool(PyObject *self, PyObject * args)
3844{
3845        PyObject *ret = NULL;
3846
3847        if (PyArg_ParseTuple(args, ""))
3848        {
3849                ret = use_bool ? Py_True : Py_False;
3850                Py_INCREF(ret);
3851        }
3852
3853        return ret;
3854}
3855
3856/* set usage of bool values */
3857static char set_bool__doc__[] =
3858"set_bool(bool) -- set whether boolean values should be converted to bool.";
3859
3860static PyObject *
3861set_bool(PyObject *self, PyObject * args)
3862{
3863        PyObject *ret = NULL;
3864        int                     i;
3865
3866        /* gets arguments */
3867        if (PyArg_ParseTuple(args, "i", &i))
3868        {
3869                use_bool = i ? 1 : 0;
3870                Py_INCREF(Py_None); ret = Py_None;
3871        }
3872
3873        return ret;
3874}
3875
3876/* get named result factory */
3877static char get_namedresult__doc__[] =
3878"get_namedresult(cls) -- get the function used for getting named results.";
3879
3880static PyObject *
3881get_namedresult(PyObject *self, PyObject *args)
3882{
3883        PyObject *ret = NULL;
3884
3885        if (PyArg_ParseTuple(args, ""))
3886        {
3887                ret = namedresult ? namedresult : Py_None;
3888                Py_INCREF(ret);
3889        }
3890
3891        return ret;
3892}
3893
3894/* set named result factory */
3895static char set_namedresult__doc__[] =
3896"set_namedresult(cls) -- set a function to be used for getting named results.";
3897
3898static PyObject *
3899set_namedresult(PyObject *self, PyObject *args)
3900{
3901        PyObject *ret = NULL;
3902        PyObject *func;
3903
3904        if (PyArg_ParseTuple(args, "O", &func))
3905        {
3906                if (PyCallable_Check(func))
3907                {
3908                        Py_XINCREF(func); Py_XDECREF(namedresult); namedresult = func;
3909                        Py_INCREF(Py_None); ret = Py_None;
3910                }
3911                else
3912                        PyErr_SetString(PyExc_TypeError, "parameter must be callable");
3913        }
3914
3915        return ret;
3916}
3917
3918#ifdef DEFAULT_VARS
3919
3920/* gets default host */
3921static char getdefhost__doc__[] =
3922"get_defhost() -- return default database host.";
3923
3924static PyObject *
3925pggetdefhost(PyObject *self, PyObject *args)
3926{
3927        /* checks args */
3928        if (!PyArg_ParseTuple(args, ""))
3929        {
3930                PyErr_SetString(PyExc_TypeError,
3931                        "method get_defhost() takes no parameter.");
3932                return NULL;
3933        }
3934
3935        Py_XINCREF(pg_default_host);
3936        return pg_default_host;
3937}
3938
3939/* sets default host */
3940static char setdefhost__doc__[] =
3941"set_defhost(string) -- set default database host. Return previous value.";
3942
3943static PyObject *
3944pgsetdefhost(PyObject *self, PyObject *args)
3945{
3946        char       *temp = NULL;
3947        PyObject   *old;
3948
3949        /* gets arguments */
3950        if (!PyArg_ParseTuple(args, "z", &temp))
3951        {
3952                PyErr_SetString(PyExc_TypeError,
3953                        "set_defhost(name), with name (string/None).");
3954                return NULL;
3955        }
3956
3957        /* adjusts value */
3958        old = pg_default_host;
3959
3960        if (temp)
3961                pg_default_host = PyString_FromString(temp);
3962        else
3963        {
3964                Py_INCREF(Py_None);
3965                pg_default_host = Py_None;
3966        }
3967
3968        return old;
3969}
3970
3971/* gets default base */
3972static char getdefbase__doc__[] =
3973"get_defbase() -- return default database name.";
3974
3975static PyObject *
3976pggetdefbase(PyObject *self, PyObject *args)
3977{
3978        /* checks args */
3979        if (!PyArg_ParseTuple(args, ""))
3980        {
3981                PyErr_SetString(PyExc_TypeError,
3982                        "method get_defbase() takes no parameter.");
3983                return NULL;
3984        }
3985
3986        Py_XINCREF(pg_default_base);
3987        return pg_default_base;
3988}
3989
3990/* sets default base */
3991static char setdefbase__doc__[] =
3992"set_defbase(string) -- set default database name. Return previous value";
3993
3994static PyObject *
3995pgsetdefbase(PyObject *self, PyObject *args)
3996{
3997        char       *temp = NULL;
3998        PyObject   *old;
3999
4000        /* gets arguments */
4001        if (!PyArg_ParseTuple(args, "z", &temp))
4002        {
4003                PyErr_SetString(PyExc_TypeError,
4004                        "set_defbase(name), with name (string/None).");
4005                return NULL;
4006        }
4007
4008        /* adjusts value */
4009        old = pg_default_base;
4010
4011        if (temp)
4012                pg_default_base = PyString_FromString(temp);
4013        else
4014        {
4015                Py_INCREF(Py_None);
4016                pg_default_base = Py_None;
4017        }
4018
4019        return old;
4020}
4021
4022/* gets default options */
4023static char getdefopt__doc__[] =
4024"get_defopt() -- return default database options.";
4025
4026static PyObject *
4027pggetdefopt(PyObject *self, PyObject *args)
4028{
4029        /* checks args */
4030        if (!PyArg_ParseTuple(args, ""))
4031        {
4032                PyErr_SetString(PyExc_TypeError,
4033                        "method get_defopt() takes no parameter.");
4034                return NULL;
4035        }
4036
4037        Py_XINCREF(pg_default_opt);
4038        return pg_default_opt;
4039}
4040
4041/* sets default opt */
4042static char setdefopt__doc__[] =
4043"set_defopt(string) -- set default database options. Return previous value.";
4044
4045static PyObject *
4046pgsetdefopt(PyObject *self, PyObject *args)
4047{
4048        char       *temp = NULL;
4049        PyObject   *old;
4050
4051        /* gets arguments */
4052        if (!PyArg_ParseTuple(args, "z", &temp))
4053        {
4054                PyErr_SetString(PyExc_TypeError,
4055                        "set_defopt(name), with name (string/None).");
4056                return NULL;
4057        }
4058
4059        /* adjusts value */
4060        old = pg_default_opt;
4061
4062        if (temp)
4063                pg_default_opt = PyString_FromString(temp);
4064        else
4065        {
4066                Py_INCREF(Py_None);
4067                pg_default_opt = Py_None;
4068        }
4069
4070        return old;
4071}
4072
4073/* gets default tty */
4074static char getdeftty__doc__[] =
4075"get_deftty() -- return default database debug terminal.";
4076
4077static PyObject *
4078pggetdeftty(PyObject *self, PyObject *args)
4079{
4080        /* checks args */
4081        if (!PyArg_ParseTuple(args, ""))
4082        {
4083                PyErr_SetString(PyExc_TypeError,
4084                        "method get_deftty() takes no parameter.");
4085                return NULL;
4086        }
4087
4088        Py_XINCREF(pg_default_tty);
4089        return pg_default_tty;
4090}
4091
4092/* sets default tty */
4093static char setdeftty__doc__[] =
4094"set_deftty(string) -- set default database debug terminal. "
4095"Return previous value.";
4096
4097static PyObject *
4098pgsetdeftty(PyObject *self, PyObject *args)
4099{
4100        char       *temp = NULL;
4101        PyObject   *old;
4102
4103        /* gets arguments */
4104        if (!PyArg_ParseTuple(args, "z", &temp))
4105        {
4106                PyErr_SetString(PyExc_TypeError,
4107                        "set_deftty(name), with name (string/None).");
4108                return NULL;
4109        }
4110
4111        /* adjusts value */
4112        old = pg_default_tty;
4113
4114        if (temp)
4115                pg_default_tty = PyString_FromString(temp);
4116        else
4117        {
4118                Py_INCREF(Py_None);
4119                pg_default_tty = Py_None;
4120        }
4121
4122        return old;
4123}
4124
4125/* gets default username */
4126static char getdefuser__doc__[] =
4127"get_defuser() -- return default database username.";
4128
4129static PyObject *
4130pggetdefuser(PyObject *self, PyObject *args)
4131{
4132        /* checks args */
4133        if (!PyArg_ParseTuple(args, ""))
4134        {
4135                PyErr_SetString(PyExc_TypeError,
4136                        "method get_defuser() takes no parameter.");
4137
4138                return NULL;
4139        }
4140
4141        Py_XINCREF(pg_default_user);
4142        return pg_default_user;
4143}
4144
4145/* sets default username */
4146static char setdefuser__doc__[] =
4147"set_defuser() -- set default database username. Return previous value.";
4148
4149static PyObject *
4150pgsetdefuser(PyObject *self, PyObject *args)
4151{
4152        char       *temp = NULL;
4153        PyObject   *old;
4154
4155        /* gets arguments */
4156        if (!PyArg_ParseTuple(args, "z", &temp))
4157        {
4158                PyErr_SetString(PyExc_TypeError,
4159                        "set_defuser(name), with name (string/None).");
4160                return NULL;
4161        }
4162
4163        /* adjusts value */
4164        old = pg_default_user;
4165
4166        if (temp)
4167                pg_default_user = PyString_FromString(temp);
4168        else
4169        {
4170                Py_INCREF(Py_None);
4171                pg_default_user = Py_None;
4172        }
4173
4174        return old;
4175}
4176
4177/* sets default password */
4178static char setdefpasswd__doc__[] =
4179"set_defpasswd() -- set default database password.";
4180
4181static PyObject *
4182pgsetdefpasswd(PyObject *self, PyObject *args)
4183{
4184        char       *temp = NULL;
4185
4186        /* gets arguments */
4187        if (!PyArg_ParseTuple(args, "z", &temp))
4188        {
4189                PyErr_SetString(PyExc_TypeError,
4190                        "set_defpasswd(password), with password (string/None).");
4191                return NULL;
4192        }
4193
4194        if (temp)
4195                pg_default_passwd = PyString_FromString(temp);
4196        else
4197        {
4198                Py_INCREF(Py_None);
4199                pg_default_passwd = Py_None;
4200        }
4201
4202        Py_INCREF(Py_None);
4203        return Py_None;
4204}
4205
4206/* gets default port */
4207static char getdefport__doc__[] =
4208"get_defport() -- return default database port.";
4209
4210static PyObject *
4211pggetdefport(PyObject *self, PyObject *args)
4212{
4213        /* checks args */
4214        if (!PyArg_ParseTuple(args, ""))
4215        {
4216                PyErr_SetString(PyExc_TypeError,
4217                        "method get_defport() takes no parameter.");
4218                return NULL;
4219        }
4220
4221        Py_XINCREF(pg_default_port);
4222        return pg_default_port;
4223}
4224
4225/* sets default port */
4226static char setdefport__doc__[] =
4227"set_defport(integer) -- set default database port. Return previous value.";
4228
4229static PyObject *
4230pgsetdefport(PyObject *self, PyObject *args)
4231{
4232        long int        port = -2;
4233        PyObject   *old;
4234
4235        /* gets arguments */
4236        if ((!PyArg_ParseTuple(args, "l", &port)) || (port < -1))
4237        {
4238                PyErr_SetString(PyExc_TypeError, "set_defport(port), with port "
4239                        "(positive integer/-1).");
4240                return NULL;
4241        }
4242
4243        /* adjusts value */
4244        old = pg_default_port;
4245
4246        if (port != -1)
4247                pg_default_port = PyInt_FromLong(port);
4248        else
4249        {
4250                Py_INCREF(Py_None);
4251                pg_default_port = Py_None;
4252        }
4253
4254        return old;
4255}
4256#endif /* DEFAULT_VARS */
4257
4258/* List of functions defined in the module */
4259
4260static struct PyMethodDef pg_methods[] = {
4261        {"connect", (PyCFunction) pgconnect, METH_VARARGS|METH_KEYWORDS,
4262                        connect__doc__},
4263        {"escape_string", (PyCFunction) escape_string, METH_VARARGS,
4264                        escape_string__doc__},
4265        {"escape_bytea", (PyCFunction) escape_bytea, METH_VARARGS,
4266                        escape_bytea__doc__},
4267        {"unescape_bytea", (PyCFunction) unescape_bytea, METH_VARARGS,
4268                        unescape_bytea__doc__},
4269        {"get_decimal_point", (PyCFunction) get_decimal_point, METH_VARARGS,
4270                        get_decimal_point__doc__},
4271        {"set_decimal_point", (PyCFunction) set_decimal_point, METH_VARARGS,
4272                        set_decimal_point__doc__},
4273        {"get_decimal", (PyCFunction) get_decimal, METH_VARARGS,
4274                        get_decimal__doc__},
4275        {"set_decimal", (PyCFunction) set_decimal, METH_VARARGS,
4276                        set_decimal__doc__},
4277        {"get_bool", (PyCFunction) get_bool, METH_VARARGS, get_bool__doc__},
4278        {"set_bool", (PyCFunction) set_bool, METH_VARARGS, set_bool__doc__},
4279        {"get_namedresult", (PyCFunction) get_namedresult, METH_VARARGS,
4280                        get_namedresult__doc__},
4281        {"set_namedresult", (PyCFunction) set_namedresult, METH_VARARGS,
4282                        set_namedresult__doc__},
4283
4284#ifdef DEFAULT_VARS
4285        {"get_defhost", pggetdefhost, METH_VARARGS, getdefhost__doc__},
4286        {"set_defhost", pgsetdefhost, METH_VARARGS, setdefhost__doc__},
4287        {"get_defbase", pggetdefbase, METH_VARARGS, getdefbase__doc__},
4288        {"set_defbase", pgsetdefbase, METH_VARARGS, setdefbase__doc__},
4289        {"get_defopt", pggetdefopt, METH_VARARGS, getdefopt__doc__},
4290        {"set_defopt", pgsetdefopt, METH_VARARGS, setdefopt__doc__},
4291        {"get_deftty", pggetdeftty, METH_VARARGS, getdeftty__doc__},
4292        {"set_deftty", pgsetdeftty, METH_VARARGS, setdeftty__doc__},
4293        {"get_defport", pggetdefport, METH_VARARGS, getdefport__doc__},
4294        {"set_defport", pgsetdefport, METH_VARARGS, setdefport__doc__},
4295        {"get_defuser", pggetdefuser, METH_VARARGS, getdefuser__doc__},
4296        {"set_defuser", pgsetdefuser, METH_VARARGS, setdefuser__doc__},
4297        {"set_defpasswd", pgsetdefpasswd, METH_VARARGS, setdefpasswd__doc__},
4298#endif /* DEFAULT_VARS */
4299        {NULL, NULL} /* sentinel */
4300};
4301
4302static char pg__doc__[] = "Python interface to PostgreSQL DB";
4303
4304/* Initialization function for the module */
4305DL_EXPORT(void)
4306init_pg(void)
4307{
4308        PyObject   *mod,
4309                           *dict,
4310                           *v;
4311
4312        /* Initialize here because some WIN platforms get confused otherwise */
4313        PgType.ob_type = PgNoticeType.ob_type =
4314                PgQueryType.ob_type = PgSourceType.ob_type = &PyType_Type;
4315#ifdef LARGE_OBJECTS
4316        PglargeType.ob_type = &PyType_Type;
4317#endif
4318
4319        /* Create the module and add the functions */
4320        mod = Py_InitModule4("_pg", pg_methods, pg__doc__, NULL, PYTHON_API_VERSION);
4321        dict = PyModule_GetDict(mod);
4322
4323        /* Exceptions as defined by DB-API 2.0 */
4324        Error = PyErr_NewException("pg.Error", PyExc_StandardError, NULL);
4325        PyDict_SetItemString(dict, "Error", Error);
4326
4327        Warning = PyErr_NewException("pg.Warning", PyExc_StandardError, NULL);
4328        PyDict_SetItemString(dict, "Warning", Warning);
4329
4330        InterfaceError = PyErr_NewException("pg.InterfaceError", Error, NULL);
4331        PyDict_SetItemString(dict, "InterfaceError", InterfaceError);
4332
4333        DatabaseError = PyErr_NewException("pg.DatabaseError", Error, NULL);
4334        PyDict_SetItemString(dict, "DatabaseError", DatabaseError);
4335
4336        InternalError = PyErr_NewException("pg.InternalError", DatabaseError, NULL);
4337        PyDict_SetItemString(dict, "InternalError", InternalError);
4338
4339        OperationalError =
4340                PyErr_NewException("pg.OperationalError", DatabaseError, NULL);
4341        PyDict_SetItemString(dict, "OperationalError", OperationalError);
4342
4343        ProgrammingError =
4344                PyErr_NewException("pg.ProgrammingError", DatabaseError, NULL);
4345        PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError);
4346
4347        IntegrityError =
4348                PyErr_NewException("pg.IntegrityError", DatabaseError, NULL);
4349        PyDict_SetItemString(dict, "IntegrityError", IntegrityError);
4350
4351        DataError = PyErr_NewException("pg.DataError", DatabaseError, NULL);
4352        PyDict_SetItemString(dict, "DataError", DataError);
4353
4354        NotSupportedError =
4355                PyErr_NewException("pg.NotSupportedError", DatabaseError, NULL);
4356        PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError);
4357
4358        /* Make the version available */
4359        v = PyString_FromString(PyPgVersion);
4360        PyDict_SetItemString(dict, "version", v);
4361        PyDict_SetItemString(dict, "__version__", v);
4362        Py_DECREF(v);
4363
4364        /* results type for queries */
4365        PyDict_SetItemString(dict, "RESULT_EMPTY", PyInt_FromLong(RESULT_EMPTY));
4366        PyDict_SetItemString(dict, "RESULT_DML", PyInt_FromLong(RESULT_DML));
4367        PyDict_SetItemString(dict, "RESULT_DDL", PyInt_FromLong(RESULT_DDL));
4368        PyDict_SetItemString(dict, "RESULT_DQL", PyInt_FromLong(RESULT_DQL));
4369
4370        /* transaction states */
4371        PyDict_SetItemString(dict,"TRANS_IDLE",PyInt_FromLong(PQTRANS_IDLE));
4372        PyDict_SetItemString(dict,"TRANS_ACTIVE",PyInt_FromLong(PQTRANS_ACTIVE));
4373        PyDict_SetItemString(dict,"TRANS_INTRANS",PyInt_FromLong(PQTRANS_INTRANS));
4374        PyDict_SetItemString(dict,"TRANS_INERROR",PyInt_FromLong(PQTRANS_INERROR));
4375        PyDict_SetItemString(dict,"TRANS_UNKNOWN",PyInt_FromLong(PQTRANS_UNKNOWN));
4376
4377#ifdef LARGE_OBJECTS
4378        /* create mode for large objects */
4379        PyDict_SetItemString(dict, "INV_READ", PyInt_FromLong(INV_READ));
4380        PyDict_SetItemString(dict, "INV_WRITE", PyInt_FromLong(INV_WRITE));
4381
4382        /* position flags for lo_lseek */
4383        PyDict_SetItemString(dict, "SEEK_SET", PyInt_FromLong(SEEK_SET));
4384        PyDict_SetItemString(dict, "SEEK_CUR", PyInt_FromLong(SEEK_CUR));
4385        PyDict_SetItemString(dict, "SEEK_END", PyInt_FromLong(SEEK_END));
4386#endif /* LARGE_OBJECTS */
4387
4388#ifdef DEFAULT_VARS
4389        /* prepares default values */
4390        Py_INCREF(Py_None);
4391        pg_default_host = Py_None;
4392        Py_INCREF(Py_None);
4393        pg_default_base = Py_None;
4394        Py_INCREF(Py_None);
4395        pg_default_opt = Py_None;
4396        Py_INCREF(Py_None);
4397        pg_default_port = Py_None;
4398        Py_INCREF(Py_None);
4399        pg_default_tty = Py_None;
4400        Py_INCREF(Py_None);
4401        pg_default_user = Py_None;
4402        Py_INCREF(Py_None);
4403        pg_default_passwd = Py_None;
4404#endif /* DEFAULT_VARS */
4405
4406        /* Check for errors */
4407        if (PyErr_Occurred())
4408                Py_FatalError("can't initialize module _pg");
4409}
Note: See TracBrowser for help on using the repository browser.