Merge remote-tracking branch 'origin/pycurl' into planetlab-4_0-branch
[plcapi.git] / trunk / psycopg2 / psycopg / cursor_type.c
1 /* cursor_type.c - python interface to cursor objects
2  *
3  * Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
4  *
5  * This file is part of psycopg.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2,
10  * or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public Likcense
18  * along with this program; if not, write to the Free Software
19  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 #include <Python.h>
23 #include <structmember.h>
24 #include <string.h>
25
26 #define PSYCOPG_MODULE
27 #include "psycopg/config.h"
28 #include "psycopg/python.h"
29 #include "psycopg/psycopg.h"
30 #include "psycopg/cursor.h"
31 #include "psycopg/connection.h"
32 #include "psycopg/pqpath.h"
33 #include "psycopg/typecast.h"
34 #include "psycopg/microprotocols.h"
35 #include "psycopg/microprotocols_proto.h"
36 #include "pgversion.h"
37
38 extern PyObject *pyPsycopgTzFixedOffsetTimezone;
39
40
41 /** DBAPI methods **/
42
43 /* close method - close the cursor */
44
45 #define psyco_curs_close_doc \
46 "close() -- Close the cursor."
47
48 static PyObject *
49 psyco_curs_close(cursorObject *self, PyObject *args)
50 {
51     if (!PyArg_ParseTuple(args, "")) return NULL;
52     
53     EXC_IF_CURS_CLOSED(self);
54     
55     if (self->name != NULL) {
56         char buffer[128];
57         
58         EXC_IF_NO_MARK(self);
59         PyOS_snprintf(buffer, 127, "CLOSE %s", self->name);
60         if (pq_execute(self, buffer, 0) == -1) return NULL;
61     }
62
63     self->closed = 1;
64     Dprintf("psyco_curs_close: cursor at %p closed", self);
65
66     Py_INCREF(Py_None);
67     return Py_None;
68 }
69
70
71 /* execute method - executes a query */
72
73 /* mogrify a query string and build argument array or dict */
74
75 static int
76 _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
77 {
78     PyObject *key, *value, *n, *item;
79     char *d, *c;
80     int index = 0, force = 0;
81
82     /* from now on we'll use n and replace its value in *new only at the end,
83        just before returning. we also init *new to NULL to exit with an error
84        if we can't complete the mogrification */
85     n = *new = NULL;
86     c = PyString_AsString(fmt);
87
88     while(*c) {
89         /* handle plain percent symbol in format string */
90         if (c[0] == '%' && c[1] == '%') {
91             c+=2; force = 1;
92         }
93         
94         /* if we find '%(' then this is a dictionary, we:
95            1/ find the matching ')' and extract the key name
96            2/ locate the value in the dictionary (or return an error)
97            3/ mogrify the value into something usefull (quoting)...
98            4/ ...and add it to the new dictionary to be used as argument
99         */
100         else if (c[0] == '%' && c[1] == '(') {
101
102             /* let's have d point the end of the argument */
103             for (d = c + 2; *d && *d != ')'; d++);
104
105             if (*d == ')') {
106                 key = PyString_FromStringAndSize(c+2, d-c-2);
107                 value = PyObject_GetItem(var, key);
108                 /* key has refcnt 1, value the original value + 1 */
109                 
110                 /*  if value is NULL we did not find the key (or this is not a
111                     dictionary): let python raise a KeyError */
112                 if (value == NULL) {
113                     Py_DECREF(key); /* destroy key */
114                     Py_XDECREF(n);  /* destroy n */
115                     return -1;
116                 }
117
118                 Dprintf("_mogrify: value refcnt: %d (+1)", value->ob_refcnt);
119                 
120                 if (n == NULL) {
121                     n = PyDict_New();
122                 }
123                 
124                 if ((item = PyObject_GetItem(n, key)) == NULL) {
125                     PyObject *t = NULL;
126
127                     PyErr_Clear();
128
129                     /* None is always converted to NULL; this is an
130                        optimization over the adapting code and can go away in
131                        the future if somebody finds a None adapter usefull. */
132                     if (value == Py_None) {
133                         t = PyString_FromString("NULL");
134                         PyDict_SetItem(n, key, t);
135                         /* t is a new object, refcnt = 1, key is at 2 */
136                         
137                         /* if the value is None we need to substitute the
138                            formatting char with 's' (FIXME: this should not be
139                            necessary if we drop support for formats other than
140                            %s!) */
141                         while (*d && !isalpha(*d)) d++;
142                         if (*d) *d = 's';
143                     }
144                     else {
145                         t = microprotocol_getquoted(value, conn);
146
147                         if (t != NULL) {
148                             PyDict_SetItem(n, key, t);
149                             /* both key and t refcnt +1, key is at 2 now */
150                         }
151                         else {
152                             /* no adapter found, raise a BIG exception */
153                             Py_XDECREF(value); 
154                             Py_DECREF(n);
155                             return -1;
156                         }
157                     }
158
159                     Py_XDECREF(t); /* t dies here */
160                     /* after the DECREF value has the original refcnt plus 1
161                        if it was added to the dictionary directly; good */
162                     Py_XDECREF(value); 
163                 }
164                 else {
165                     /* we have an item with one extra refcnt here, zap! */
166                     Py_DECREF(item);
167                 }
168                 Py_DECREF(key); /* key has the original refcnt now */
169                 Dprintf("_mogrify: after value refcnt: %d",value->ob_refcnt);
170             }
171             c = d;
172         }
173         
174         else if (c[0] == '%' && c[1] != '(') {
175             /* this is a format that expects a tuple; it is much easier,
176                because we don't need to check the old/new dictionary for
177                keys */
178             
179             value = PySequence_GetItem(var, index);
180             /* value has refcnt inc'ed by 1 here */
181             
182             /*  if value is NULL this is not a sequence or the index is wrong;
183                 anyway we let python set its own exception */
184             if (value == NULL) {
185                 Py_XDECREF(n);
186                 return -1;
187             }
188
189             if (n == NULL) {
190                 n = PyTuple_New(PyObject_Length(var));
191             }
192             
193             /* let's have d point just after the '%' */
194             d = c+1;
195             
196             if (value == Py_None) {
197                 PyTuple_SET_ITEM(n, index, PyString_FromString("NULL"));
198                 while (*d && !isalpha(*d)) d++;
199                 if (*d) *d = 's';
200                 Py_DECREF(value);
201             }
202             else {
203                 PyObject *t = microprotocol_getquoted(value, conn);
204
205                 if (t != NULL) {
206                     PyTuple_SET_ITEM(n, index, t);
207                     Py_DECREF(value);
208                 }
209                 else {
210                     Py_DECREF(n);
211                     Py_DECREF(value);
212                     return -1;
213                 }
214             }
215             c = d;
216             index += 1;
217         }
218         else {
219             c++;
220         }
221     }
222
223     if (force && n == NULL)
224         n = PyTuple_New(0);
225     *new = n;
226     
227     return 0;
228 }
229     
230 #define psyco_curs_execute_doc \
231 "execute(query, vars=None, async=0) -- Execute query with bound vars."
232
233 static int
234 _psyco_curs_execute(cursorObject *self,
235                     PyObject *operation, PyObject *vars, long int async)
236 {
237     int res;
238     PyObject *fquery, *cvt = NULL, *uoperation = NULL;
239     
240     pthread_mutex_lock(&(self->conn->lock));
241     if (self->conn->async_cursor != NULL
242         && self->conn->async_cursor != (PyObject*)self) {
243         pthread_mutex_unlock(&(self->conn->lock));
244         psyco_set_error(ProgrammingError, (PyObject*)self,
245                          "asynchronous query already in execution", NULL, NULL);
246         return 0;
247     }
248     pthread_mutex_unlock(&(self->conn->lock));
249     
250     if (!PyObject_IsTrue(operation)) {
251         psyco_set_error(ProgrammingError, (PyObject*)self,
252                          "can't execute an empty query", NULL, NULL);
253         return 0;
254     }
255     
256     if (PyUnicode_Check(operation)) {
257         PyObject *enc = PyDict_GetItemString(psycoEncodings,
258                                              self->conn->encoding);
259         /* enc is a borrowed reference, we won't decref it */
260         
261         if (enc) {
262             operation = PyUnicode_AsEncodedString(
263                 operation, PyString_AsString(enc), NULL);
264
265             /* if there was an error during the encoding from unicode to the
266                target encoding we just let the exception propagate */
267             if (operation == NULL) return 0;
268
269             /* we clone operation in uoperation to be sure to free it later */ 
270             uoperation = operation;
271         }
272         else {
273             PyErr_Format(InterfaceError, "can't encode unicode query to %s",
274                          self->conn->encoding);
275             return 0;
276         }
277     }
278     else if (!PyString_Check(operation)) {
279         /* the operation is not unicode or string, raise an error */
280         PyErr_SetString(PyExc_TypeError,
281                         "argument 1 must be a string or unicode object");
282         return 0;
283     }
284     
285     IFCLEARPGRES(self->pgres);
286
287     if (self->query) {
288         Py_DECREF(self->query);
289         self->query = NULL;
290     }
291     
292     Dprintf("psyco_curs_execute: starting execution of new query");
293
294     /* here we are, and we have a sequence or a dictionary filled with
295        objects to be substituted (bound variables). we try to be smart and do
296        the right thing (i.e., what the user expects) */
297     
298     if (vars && vars != Py_None)
299     {
300         if(_mogrify(vars, operation, self->conn, &cvt) == -1) {
301             Py_XDECREF(uoperation);
302             return 0;
303         }
304     }
305
306     if (vars && cvt) {
307         /* if PyString_Format() return NULL an error occured: if the error is
308            a TypeError we need to check the exception.args[0] string for the
309            values:
310
311                "not enough arguments for format string"
312                "not all arguments converted"
313
314            and return the appropriate ProgrammingError. we do that by grabbing
315            the curren exception (we will later restore it if the type or the
316            strings do not match.) */
317         
318         if (!(fquery = PyString_Format(operation, cvt))) {
319             PyObject *err, *arg, *trace;
320             int pe = 0;
321
322             PyErr_Fetch(&err, &arg, &trace);
323             
324             if (err && PyErr_GivenExceptionMatches(err, PyExc_TypeError)) {
325                 Dprintf("psyco_curs_execute: TypeError exception catched");
326                 PyErr_NormalizeException(&err, &arg, &trace);
327
328                 if (PyObject_HasAttrString(arg, "args")) {
329                     PyObject *args = PyObject_GetAttrString(arg, "args");
330                     PyObject *str = PySequence_GetItem(args, 0);
331                     char *s = PyString_AS_STRING(str);
332
333                     Dprintf("psyco_curs_execute:     -> %s", s);
334
335                     if (!strcmp(s, "not enough arguments for format string")
336                       || !strcmp(s, "not all arguments converted")) {
337                         Dprintf("psyco_curs_execute:     -> got a match");
338                         psyco_set_error(ProgrammingError, (PyObject*)self,
339                                          s, NULL, NULL);
340                         pe = 1;
341                     }
342
343                     Py_DECREF(args);
344                     Py_DECREF(str);
345                 }
346             }
347
348             /* if we did not manage our own exception, restore old one */
349             if (pe == 1) {
350                 Py_XDECREF(err); Py_XDECREF(arg); Py_XDECREF(trace);
351             }
352             else {
353                 PyErr_Restore(err, arg, trace);
354             }
355             Py_XDECREF(uoperation);
356             return 0;
357         }
358         
359         if (self->name != NULL) {
360             self->query = PyString_FromFormat(
361                 "DECLARE %s CURSOR WITHOUT HOLD FOR %s",
362                 self->name, PyString_AS_STRING(fquery));
363             Py_DECREF(fquery);
364         }
365         else {
366             self->query = fquery;
367         }
368         
369         Dprintf("psyco_curs_execute: cvt->refcnt = %d", cvt->ob_refcnt);
370         Py_DECREF(cvt);
371     }
372     else {
373         if (self->name != NULL) {
374             self->query = PyString_FromFormat(
375                 "DECLARE %s CURSOR WITHOUT HOLD FOR %s",
376                 self->name, PyString_AS_STRING(operation));
377         }
378         else {
379             Py_INCREF(operation);
380             self->query = operation;
381         }
382     }
383     
384     res = pq_execute(self, PyString_AS_STRING(self->query), async);
385     
386     Dprintf("psyco_curs_execute: res = %d, pgres = %p", res, self->pgres);
387
388     Py_XDECREF(uoperation);
389     
390     return res == -1 ? 0 : 1;
391 }
392
393 static PyObject *
394 psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
395 {   
396     long int async = 0;
397     PyObject *vars = NULL, *operation = NULL;
398     
399     static char *kwlist[] = {"query", "vars", "async", NULL};
400
401     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi", kwlist,
402                                      &operation, &vars, &async)) {
403         return NULL;
404     }
405
406     if (self->name != NULL) {
407         if (self->query != Py_None) {
408             psyco_set_error(ProgrammingError, (PyObject*)self,
409                 "can't call .execute() on named cursors more than once",
410                 NULL, NULL);
411             return NULL;
412         }
413         if (self->conn->isolation_level == 0) {
414             psyco_set_error(ProgrammingError, (PyObject*)self,
415                 "can't use a named cursor outside of transactions", NULL, NULL);
416             return NULL;          
417         }
418         if (self->conn->mark != self->mark) {
419             psyco_set_error(ProgrammingError, (PyObject*)self,
420                 "named cursor isn't valid anymore", NULL, NULL);
421             return NULL;
422         }
423     }
424
425     EXC_IF_CURS_CLOSED(self);
426     
427     if (_psyco_curs_execute(self, operation, vars, async)) {
428         Py_INCREF(Py_None);
429         return Py_None;
430     }
431     else {
432         return NULL;
433     }
434 }
435
436 #define psyco_curs_executemany_doc \
437 "executemany(query, vars_list) -- Execute many queries with bound vars."
438
439 static PyObject *
440 psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
441 {
442     PyObject *operation = NULL, *vars = NULL;
443     PyObject *v, *iter = NULL;
444     
445     static char *kwlist[] = {"query", "vars_list", NULL};
446
447     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist,
448                                      &operation, &vars)) {
449         return NULL;
450     }
451
452     EXC_IF_CURS_CLOSED(self);
453     
454     if (self->name != NULL) {
455         psyco_set_error(ProgrammingError, (PyObject*)self,
456                 "can't call .executemany() on named cursors", NULL, NULL);
457         return NULL;
458     } 
459
460     if (!PyIter_Check(vars)) {
461         vars = iter = PyObject_GetIter(vars);
462         if (iter == NULL) return NULL;
463     }
464     
465     while ((v = PyIter_Next(vars)) != NULL) {
466         if (_psyco_curs_execute(self, operation, v, 0) == 0) {
467             Py_DECREF(v);
468             return NULL;
469         }
470         else {
471             Py_DECREF(v);
472         }
473     }
474     Py_XDECREF(iter);
475     
476     Py_INCREF(Py_None);
477     return Py_None;
478 }
479
480
481 #ifdef PSYCOPG_EXTENSIONS
482 #define psyco_curs_mogrify_doc \
483 "mogrify(query, vars=None) -> str -- Return query after vars binding."
484
485 static PyObject *
486 psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs)
487 {   
488     PyObject *vars = NULL, *cvt = NULL, *operation = NULL;
489     PyObject *fquery;
490     
491     static char *kwlist[] = {"query", "vars", NULL};
492
493     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist,
494                                      &operation, &vars)) {
495         return NULL;
496     }
497
498     if (PyUnicode_Check(operation)) {
499         PyErr_SetString(NotSupportedError,
500                         "unicode queries not yet supported");
501         return NULL;
502     }
503     
504     EXC_IF_CURS_CLOSED(self);
505     IFCLEARPGRES(self->pgres);
506
507     /* note that we don't overwrite the last query executed on the cursor, we
508        just *return* the new query with bound variables
509
510        TODO: refactor the common mogrification code (see psycopg_curs_execute
511        for comments, the code is amost identical) */
512
513     if (vars)
514     {
515         if(_mogrify(vars, operation, self->conn, &cvt) == -1) return NULL;
516     }
517
518     if (vars && cvt) {        
519         if (!(fquery = PyString_Format(operation, cvt))) {
520             PyObject *err, *arg, *trace;
521             int pe = 0;
522
523             PyErr_Fetch(&err, &arg, &trace);
524             
525             if (err && PyErr_GivenExceptionMatches(err, PyExc_TypeError)) {
526                 Dprintf("psyco_curs_execute: TypeError exception catched");
527                 PyErr_NormalizeException(&err, &arg, &trace);
528
529                 if (PyObject_HasAttrString(arg, "args")) {
530                     PyObject *args = PyObject_GetAttrString(arg, "args");
531                     PyObject *str = PySequence_GetItem(args, 0);
532                     char *s = PyString_AS_STRING(str);
533
534                     Dprintf("psyco_curs_execute:     -> %s", s);
535
536                     if (!strcmp(s, "not enough arguments for format string")
537                       || !strcmp(s, "not all arguments converted")) {
538                         Dprintf("psyco_curs_execute:     -> got a match");
539                         psyco_set_error(ProgrammingError, (PyObject*)self,
540                                          s, NULL, NULL);
541                         pe = 1;
542                     }
543
544                     Py_DECREF(args);
545                     Py_DECREF(str);
546                 }
547             }
548
549             /* if we did not manage our own exception, restore old one */
550             if (pe == 1) {
551                 Py_XDECREF(err); Py_XDECREF(arg); Py_XDECREF(trace);
552             }
553             else {
554                 PyErr_Restore(err, arg, trace);
555             }
556             return NULL;
557         }
558
559         Dprintf("psyco_curs_execute: cvt->refcnt = %d, fquery->refcnt = %d",
560                 cvt->ob_refcnt, fquery->ob_refcnt);
561         Py_DECREF(cvt);
562     }
563     else {
564         fquery = operation;
565         Py_INCREF(operation);
566     }
567
568     return fquery;
569 }
570 #endif
571
572
573 /* fetchone method - fetch one row of results */
574
575 #define psyco_curs_fetchone_doc \
576 "fetchone() -> tuple or None\n\n" \
577 "Return the next row of a query result set in the form of a tuple (by\n" \
578 "default) or using the sequence factory previously set in the\n" \
579 "`row_factory` attribute. Return `None` when no more data is available.\n"
580
581 static int
582 _psyco_curs_prefetch(cursorObject *self)
583 {
584     int i = 0;
585     
586     /* check if the fetching cursor is the one that did the asynchronous query
587        and raise an exception if not */
588     pthread_mutex_lock(&(self->conn->lock));
589     if (self->conn->async_cursor != NULL
590         && self->conn->async_cursor != (PyObject*)self) {
591         pthread_mutex_unlock(&(self->conn->lock));
592         psyco_set_error(ProgrammingError, (PyObject*)self,
593                          "asynchronous fetch by wrong cursor", NULL, NULL);
594         return -2;
595     }
596     pthread_mutex_unlock(&(self->conn->lock));
597     
598     if (self->pgres == NULL || self->needsfetch) {
599         self->needsfetch = 0;
600         Dprintf("_psyco_curs_prefetch: trying to fetch data");
601         do {
602             i = pq_fetch(self);
603             Dprintf("_psycopg_curs_prefetch: result = %d", i);
604         } while(i == 1);
605     }
606
607     Dprintf("_psyco_curs_prefetch: result = %d", i);
608     return i;
609 }
610
611 static PyObject *
612 _psyco_curs_buildrow_fill(cursorObject *self, PyObject *res,
613                           int row, int n, int istuple)
614 {
615     int i, len;
616     unsigned char *str;
617     PyObject *val;
618     
619     for (i=0; i < n; i++) {
620         if (PQgetisnull(self->pgres, row, i)) {
621             str = NULL;
622             len = 0;
623         }
624         else {
625             str = (unsigned char*)PQgetvalue(self->pgres, row, i);
626             len = PQgetlength(self->pgres, row, i);
627         }
628
629         Dprintf("_psyco_curs_buildrow: row %ld, element %d, len %i",
630                 self->row, i, len);
631
632         val = typecast_cast(PyTuple_GET_ITEM(self->casts, i), (char*)str, len,
633                             (PyObject*)self);
634
635         if (val) {
636             Dprintf("_psyco_curs_buildrow: val->refcnt = %d", val->ob_refcnt);
637             if (istuple) {
638                 PyTuple_SET_ITEM(res, i, val);
639             }
640             else {
641                 PySequence_SetItem(res, i, val);
642                 Py_DECREF(val);
643             }
644         }
645         else {
646             /* an error occurred in the type system, we return NULL to raise
647                an exception. the typecast code should already have set the
648                exception type and text */
649             Py_DECREF(res);
650             res = NULL;
651             break;
652         }
653     }
654     return res;
655 }
656
657 static PyObject *
658 _psyco_curs_buildrow(cursorObject *self, int row)
659 {
660     int n;
661     
662     n = PQnfields(self->pgres);
663     return _psyco_curs_buildrow_fill(self, PyTuple_New(n), row, n, 1);
664 }
665
666 static PyObject *
667 _psyco_curs_buildrow_with_factory(cursorObject *self, int row)
668 {
669     int n;
670     PyObject *res;
671
672     n = PQnfields(self->pgres);
673     if ((res = PyObject_CallFunction(self->tuple_factory, "O", self))== NULL)
674         return NULL;
675
676     return _psyco_curs_buildrow_fill(self, res, row, n, 0);
677 }
678
679 PyObject *
680 psyco_curs_fetchone(cursorObject *self, PyObject *args)
681 {
682     PyObject *res;
683     
684     if (args && !PyArg_ParseTuple(args, "")) return NULL;
685     
686     EXC_IF_CURS_CLOSED(self)
687     if (_psyco_curs_prefetch(self) < 0) return NULL;
688     EXC_IF_NO_TUPLES(self);
689     
690     if (self->name != NULL) {
691         char buffer[128];
692         
693         EXC_IF_NO_MARK(self);
694         PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM %s", self->name);
695         if (pq_execute(self, buffer, 0) == -1) return NULL;
696         if (_psyco_curs_prefetch(self) < 0) return NULL;
697     }
698     
699     Dprintf("psyco_curs_fetchone: fetching row %ld", self->row);
700     Dprintf("psyco_curs_fetchone: rowcount = %ld", self->rowcount); 
701
702     if (self->row >= self->rowcount) {
703         /* we exausted available data: return None */
704         Py_INCREF(Py_None);
705         return Py_None;
706     }
707
708     if (self->tuple_factory == Py_None)
709         res = _psyco_curs_buildrow(self, self->row);
710     else
711         res = _psyco_curs_buildrow_with_factory(self, self->row);
712     
713     self->row++; /* move the counter to next line */
714
715     /* if the query was async aggresively free pgres, to allow
716        successive requests to reallocate it */
717     if (self->row >= self->rowcount
718         && self->conn->async_cursor == (PyObject*)self)
719         IFCLEARPGRES(self->pgres);
720
721     return res;
722 }
723
724
725 /* fetch many - fetch some results */
726
727 #define psyco_curs_fetchmany_doc \
728 "fetchmany(size=self.arraysize) -> list of tuple\n\n" \
729 "Return the next `size` rows of a query result set in the form of a list\n" \
730 "of tuples (by default) or using the sequence factory previously set in\n" \
731 "the `row_factory` attribute. Return `None` when no more data is available.\n"
732
733 PyObject *
734 psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
735 {
736     int i;
737     PyObject *list, *res;
738     
739     long int size = self->arraysize;
740     static char *kwlist[] = {"size", NULL};
741     
742     if (!PyArg_ParseTupleAndKeywords(args, kwords, "|l", kwlist, &size)) {
743         return NULL;
744     }
745
746     EXC_IF_CURS_CLOSED(self);
747     if (_psyco_curs_prefetch(self) < 0) return NULL;
748     EXC_IF_NO_TUPLES(self);
749
750     if (self->name != NULL) {
751         char buffer[128];
752         
753         EXC_IF_NO_MARK(self);
754         PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM %s",
755             (int)size, self->name);
756         if (pq_execute(self, buffer, 0) == -1) return NULL;
757         if (_psyco_curs_prefetch(self) < 0) return NULL;
758     }
759
760     /* make sure size is not > than the available number of rows */
761     if (size > self->rowcount - self->row || size < 0) {
762         size = self->rowcount - self->row;
763     }
764
765     Dprintf("psyco_curs_fetchmany: size = %ld", size);
766     
767     if (size <= 0) {
768         return PyList_New(0);
769     }
770     
771     list = PyList_New(size);
772     
773     for (i = 0; i < size; i++) {
774         if (self->tuple_factory == Py_None)
775             res = _psyco_curs_buildrow(self, self->row);
776         else
777             res = _psyco_curs_buildrow_with_factory(self, self->row);
778         
779         self->row++;
780
781         if (res == NULL) {
782             Py_DECREF(list);
783             return NULL;
784         }
785
786         PyList_SET_ITEM(list, i, res);
787     }
788
789     /* if the query was async aggresively free pgres, to allow
790        successive requests to reallocate it */
791     if (self->row >= self->rowcount
792         && self->conn->async_cursor == (PyObject*)self)
793         IFCLEARPGRES(self->pgres);
794     
795     return list;
796 }
797
798
799 /* fetch all - fetch all results */
800
801 #define psyco_curs_fetchall_doc \
802 "fetchall() -> list of tuple\n\n" \
803 "Return all the remaining rows of a query result set.\n\n" \
804 "Rows are returned in the form of a list of tuples (by default) or using\n" \
805 "the sequence factory previously set in the `row_factory` attribute.\n" \
806 "Return `None` when no more data is available.\n"
807
808 PyObject *
809 psyco_curs_fetchall(cursorObject *self, PyObject *args)
810 {
811     int i, size;
812     PyObject *list, *res;
813
814     if (!PyArg_ParseTuple(args, "")) {
815         return NULL;
816     }
817
818     EXC_IF_CURS_CLOSED(self);
819     if (_psyco_curs_prefetch(self) < 0) return NULL;
820     EXC_IF_NO_TUPLES(self);
821     
822     if (self->name != NULL) {
823         char buffer[128];
824         
825         EXC_IF_NO_MARK(self);
826         PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM %s", self->name);
827         if (pq_execute(self, buffer, 0) == -1) return NULL;
828         if (_psyco_curs_prefetch(self) < 0) return NULL;
829     }
830
831     size = self->rowcount - self->row;
832     
833     if (size <= 0) {
834         return PyList_New(0);
835     }
836     
837     list = PyList_New(size);
838     
839     for (i = 0; i < size; i++) {
840         if (self->tuple_factory == Py_None)
841             res = _psyco_curs_buildrow(self, self->row);
842         else
843             res = _psyco_curs_buildrow_with_factory(self, self->row);
844         
845         self->row++;
846
847         if (res == NULL) {
848             Py_DECREF(list);
849             return NULL;
850         }
851
852         PyList_SET_ITEM(list, i, res);
853     }
854
855     /* if the query was async aggresively free pgres, to allow
856        successive requests to reallocate it */
857     if (self->row >= self->rowcount
858         && self->conn->async_cursor == (PyObject*)self)
859         IFCLEARPGRES(self->pgres);
860     
861     return list;
862 }
863
864
865 /* callproc method - execute a stored procedure */
866
867 #define psyco_curs_callproc_doc \
868 "callproc(procname, parameters=None, async=0) -- Execute stored procedure."
869
870 static PyObject *
871 psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
872 {
873     char *procname = NULL, *sql = NULL;
874     long int async = 0;
875     int i, nparameters = 0, sl = 0;
876     PyObject *parameters = NULL;
877     PyObject *operation = NULL;
878     PyObject *res = NULL;
879
880     if (!PyArg_ParseTuple(args, "s|Oi", &procname, &parameters, &async)) {
881         return NULL;
882     }
883
884     EXC_IF_CURS_CLOSED(self);
885
886     if (self->name != NULL) {
887         psyco_set_error(ProgrammingError, (PyObject*)self,
888                          "can't call .callproc() on named cursors", NULL, NULL);
889         return NULL;
890     } 
891
892     if(parameters && parameters != Py_None) {
893         nparameters = PyObject_Length(parameters);
894         if (nparameters < 0) nparameters = 0;
895     }
896
897     /* allocate some memory, build the SQL and create a PyString from it */
898     sl = strlen(procname) + 10 + nparameters*3 - (nparameters ? 1 : 0);
899     sql = (char*)PyMem_Malloc(sl);
900     if (sql == NULL) return NULL;
901     
902     sprintf(sql, "SELECT %s(", procname);
903     for(i=0; i<nparameters; i++) {
904         strcat(sql, "%s,");
905     }
906     sql[sl-2] = ')';
907     sql[sl-1] = '\0';
908     
909     operation = PyString_FromString(sql);
910     PyMem_Free((void*)sql);
911     
912     if (_psyco_curs_execute(self, operation, parameters, async)) {
913         Py_INCREF(Py_None);
914         res = Py_None;
915     }
916
917     Py_DECREF(operation);
918     return res;
919 }
920
921
922 /* nextset method - return the next set of data (not supported) */
923
924 #define psyco_curs_nextset_doc \
925 "nextset() -- Skip to next set of data.\n\n" \
926 "This method is not supported (PostgreSQL does not have multiple data \n" \
927 "sets) and will raise a NotSupportedError exception."
928
929 static PyObject *
930 psyco_curs_nextset(cursorObject *self, PyObject *args)
931 {
932     if (!PyArg_ParseTuple(args, "")) return NULL;
933     
934     EXC_IF_CURS_CLOSED(self);
935
936     PyErr_SetString(NotSupportedError, "not supported by PostgreSQL");
937     return NULL;
938 }
939
940
941 /* setinputsizes - predefine memory areas for execute (does nothing) */
942
943 #define psyco_curs_setinputsizes_doc \
944 "setinputsizes(sizes) -- Set memory areas before execute.\n\n" \
945 "This method currently does nothing but it is safe to call it."
946
947 static PyObject *
948 psyco_curs_setinputsizes(cursorObject *self, PyObject *args)
949 {
950     PyObject *sizes;
951     
952     if (!PyArg_ParseTuple(args, "O", &sizes))
953         return NULL;
954     
955     EXC_IF_CURS_CLOSED(self);
956
957     Py_INCREF(Py_None);
958     return Py_None;
959 }
960
961
962 /* setoutputsize - predefine memory areas for execute (does nothing) */
963
964 #define psyco_curs_setoutputsize_doc \
965 "setoutputsize(size, column=None) -- Set column buffer size.\n\n" \
966 "This method currently does nothing but it is safe to call it."
967
968 static PyObject *
969 psyco_curs_setoutputsize(cursorObject *self, PyObject *args)
970 {
971     long int size, column;
972     
973     if (!PyArg_ParseTuple(args, "l|l", &size, &column))
974         return NULL;
975     
976     EXC_IF_CURS_CLOSED(self);
977
978     Py_INCREF(Py_None);
979     return Py_None;
980 }
981
982
983 /* scroll - scroll position in result list */
984
985 #define psyco_curs_scroll_doc \
986 "scroll(value, mode='relative') -- Scroll to new position according to mode." 
987
988 static PyObject *
989 psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
990 {
991     int value, newpos;
992     char *mode = "relative";
993
994     static char *kwlist[] = {"value", "mode", NULL};
995
996     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|s",
997                                      kwlist, &value, &mode))
998         return NULL;
999     
1000     EXC_IF_CURS_CLOSED(self);
1001
1002     /* if the cursor is not named we have the full result set and we can do
1003        our own calculations to scroll; else we just delegate the scrolling
1004        to the MOVE SQL statement */
1005     if (self->name == NULL) {
1006         if (strcmp(mode, "relative") == 0) {
1007             newpos = self->row + value;
1008         } else if (strcmp( mode, "absolute") == 0) {
1009             newpos = value;
1010         } else {
1011             psyco_set_error(ProgrammingError, (PyObject*)self,
1012                 "scroll mode must be 'relative' or 'absolute'", NULL, NULL);
1013             return NULL;
1014         }
1015     
1016         if (newpos < 0 || newpos >= self->rowcount ) {
1017             psyco_set_error(ProgrammingError, (PyObject*)self,
1018                              "scroll destination out of bounds", NULL, NULL);
1019             return NULL;
1020         }
1021         
1022         self->row = newpos;
1023     }
1024     
1025     else {
1026         char buffer[128];
1027         
1028         EXC_IF_NO_MARK(self);
1029         
1030         if (strcmp(mode, "absolute") == 0) {
1031             PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM %s",
1032                 value, self->name);
1033         }
1034         else {
1035             PyOS_snprintf(buffer, 127, "MOVE %d FROM %s", value, self->name);
1036         }
1037         if (pq_execute(self, buffer, 0) == -1) return NULL;
1038         if (_psyco_curs_prefetch(self) < 0) return NULL;
1039     }
1040
1041     Py_INCREF(Py_None);
1042     return Py_None;
1043 }
1044
1045
1046 #ifdef PSYCOPG_EXTENSIONS
1047
1048 /* extension: copy_from - implements COPY FROM */
1049
1050 #define psyco_curs_copy_from_doc \
1051 "copy_from(file, table, sep='\\t', null='\\N', columns=None) -- Copy table from file."
1052
1053 static int
1054 _psyco_curs_has_read_check(PyObject* o, void* var)
1055 {
1056     if (PyObject_HasAttrString(o, "readline")
1057         && PyObject_HasAttrString(o, "read")) {
1058         Py_INCREF(o);
1059         *((PyObject**)var) = o;
1060         return 1;
1061     }
1062     else {
1063         PyErr_SetString(PyExc_TypeError,
1064             "argument 1 must have both .read() and .readline() methods");
1065         return 0;
1066     }   
1067 }
1068
1069 static PyObject *
1070 psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
1071 {
1072     char query[1024];
1073     char *table_name;
1074     char *sep = "\t", *null = NULL;
1075     long int bufsize = DEFAULT_COPYSIZE;
1076     PyObject *file, *columns = NULL, *res = NULL;
1077     char columnlist[1024] = "";
1078
1079     static char *kwlist[] = {"file", "table", "sep", "null", "size", 
1080                              "columns", NULL};
1081
1082     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ssiO", kwlist,
1083                                      _psyco_curs_has_read_check, &file,
1084                                      &table_name, &sep, &null, &bufsize,
1085                                      &columns)) {
1086         return NULL;
1087     }
1088     
1089     if (columns != NULL && columns != Py_None) {
1090         PyObject* collistiter = PyObject_GetIter(columns);
1091         PyObject* col;
1092         int collistlen = 2;
1093         int colitemlen;
1094         char* colname;
1095         if (collistiter == NULL) {
1096             return NULL;
1097         }
1098         strcpy(columnlist, " (");
1099         while ((col = PyIter_Next(collistiter)) != NULL) {
1100             if (!PyString_Check(col)) {
1101                 Py_DECREF(col);
1102                 Py_DECREF(collistiter);
1103                 PyErr_SetString(PyExc_ValueError,
1104                     "Elements in column list must be strings");
1105                 return NULL;
1106             }
1107             PyString_AsStringAndSize(col, &colname, &colitemlen);
1108             if (collistlen + colitemlen > 1022) {
1109                 Py_DECREF(col);
1110                 Py_DECREF(collistiter);
1111                 PyErr_SetString(PyExc_ValueError, "Column list too long");
1112                 return NULL;
1113             }
1114             strncpy(&columnlist[collistlen], colname, colitemlen);
1115             collistlen += colitemlen;
1116             columnlist[collistlen++] = ',';
1117             Py_DECREF(col);
1118         }
1119         Py_DECREF(collistiter);
1120
1121         if (collistlen == 2) {  /* empty list; we printed no comma */
1122             collistlen++;
1123         }
1124
1125         columnlist[collistlen - 1] = ')';
1126         columnlist[collistlen] = '\0';
1127     }
1128
1129     if (PyErr_Occurred()) {
1130         return NULL;
1131     }
1132
1133     EXC_IF_CURS_CLOSED(self);
1134
1135     if (null) {
1136         PyOS_snprintf(query, 1023, "COPY %s%s FROM stdin USING DELIMITERS '%s'"
1137                       " WITH NULL AS '%s'", table_name, columnlist, sep, null);
1138     }
1139     else {
1140         PyOS_snprintf(query, 1023, "COPY %s%s FROM stdin USING DELIMITERS '%s'",
1141                       table_name, columnlist, sep);
1142     }
1143     Dprintf("psyco_curs_copy_from: query = %s", query);
1144
1145     self->copysize = bufsize;
1146     self->copyfile = file;
1147
1148     if (pq_execute(self, query, 0) == 1) {
1149         res = Py_None;
1150         Py_INCREF(Py_None);
1151     }
1152
1153     self->copyfile =NULL;
1154     
1155     return res;
1156 }
1157
1158 #define psyco_curs_copy_to_doc \
1159 "copy_to(file, table, sep='\\t', null='\\N') -- Copy table to file."
1160
1161 static int
1162 _psyco_curs_has_write_check(PyObject* o, void* var)
1163 {
1164     if (PyObject_HasAttrString(o, "write")) {
1165         Py_INCREF(o);
1166         *((PyObject**)var) = o;
1167         return 1;
1168     }
1169     else {
1170         PyErr_SetString(PyExc_TypeError,
1171                         "argument 1 must have a .write() method");
1172         return 0;
1173     }   
1174 }
1175
1176 static PyObject *
1177 psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
1178 {
1179     char query[256];
1180     char *table_name;
1181     char *sep = "\t", *null = NULL;
1182     PyObject *file, *res = NULL;
1183
1184     static char *kwlist[] = {"file", "table", "sep", "null", NULL};
1185
1186     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ss", kwlist,
1187                                      _psyco_curs_has_write_check, &file,
1188                                      &table_name, &sep, &null)) {
1189         return NULL;
1190     }
1191     
1192     EXC_IF_CURS_CLOSED(self);
1193
1194     if (null) {
1195         PyOS_snprintf(query, 255, "COPY %s TO stdout USING DELIMITERS '%s'"
1196                       " WITH NULL AS '%s'", table_name, sep, null);
1197     }
1198     else {
1199         PyOS_snprintf(query, 255, "COPY %s TO stdout USING DELIMITERS '%s'",
1200                       table_name, sep);
1201     }
1202
1203     self->copysize = 0;
1204     self->copyfile = file;
1205
1206     if (pq_execute(self, query, 0) == 1) {
1207         res = Py_None;
1208         Py_INCREF(Py_None);   
1209     }
1210     
1211     self->copyfile = NULL;
1212     
1213     return res;
1214 }   
1215 /* extension: fileno - return the file descripor of the connection */
1216
1217 #define psyco_curs_fileno_doc \
1218 "fileno() -> int -- Return file descriptor associated to database connection."
1219
1220 static PyObject *
1221 psyco_curs_fileno(cursorObject *self, PyObject *args)
1222 {
1223     long int socket;
1224     
1225     if (!PyArg_ParseTuple(args, "")) return NULL;
1226     EXC_IF_CURS_CLOSED(self);
1227
1228     /* note how we call PQflush() to make sure the user will use
1229        select() in the safe way! */
1230     pthread_mutex_lock(&(self->conn->lock));
1231     Py_BEGIN_ALLOW_THREADS;
1232     PQflush(self->conn->pgconn);
1233     socket = (long int)PQsocket(self->conn->pgconn);
1234     Py_END_ALLOW_THREADS;
1235     pthread_mutex_unlock(&(self->conn->lock));
1236
1237     return PyInt_FromLong(socket);
1238 }
1239
1240 /* extension: isready - return true if data from async execute is ready */
1241
1242 #define psyco_curs_isready_doc \
1243 "isready() -> bool -- Return True if data is ready after an async query."
1244
1245 static PyObject *
1246 psyco_curs_isready(cursorObject *self, PyObject *args)
1247 {
1248     if (!PyArg_ParseTuple(args, "")) return NULL;
1249     EXC_IF_CURS_CLOSED(self);
1250
1251     /* pq_is_busy does its own locking, we don't need anything special but if
1252        the cursor is ready we need to fetch the result and free the connection
1253        for the next query. */
1254     
1255     if (pq_is_busy(self->conn)) {
1256         Py_INCREF(Py_False);
1257         return Py_False;
1258     }
1259     else {
1260         IFCLEARPGRES(self->pgres);
1261         pthread_mutex_lock(&(self->conn->lock));
1262         self->pgres = PQgetResult(self->conn->pgconn);
1263         self->conn->async_cursor = NULL;
1264         pthread_mutex_unlock(&(self->conn->lock));
1265         self->needsfetch = 1;
1266         Py_INCREF(Py_True);
1267         return Py_True;
1268     }
1269 }
1270
1271 #endif
1272
1273
1274 /** the cursor object **/
1275
1276 /* iterator protocol */
1277
1278 static PyObject *
1279 cursor_iter(PyObject *self)
1280 {
1281     EXC_IF_CURS_CLOSED((cursorObject*)self);
1282     Py_INCREF(self);
1283     return self;
1284 }
1285
1286 static PyObject *
1287 cursor_next(PyObject *self)
1288 {
1289     PyObject *res;
1290
1291     /* we don't parse arguments: psyco_curs_fetchone will do that for us */
1292     res = psyco_curs_fetchone((cursorObject*)self, NULL);
1293
1294     /* convert a None to NULL to signal the end of iteration */
1295     if (res && res == Py_None) {
1296         Py_DECREF(res);
1297         res = NULL;
1298     }
1299     return res;
1300 }
1301
1302 /* object method list */
1303
1304 static struct PyMethodDef cursorObject_methods[] = {
1305     /* DBAPI-2.0 core */
1306     {"close", (PyCFunction)psyco_curs_close,
1307      METH_VARARGS, psyco_curs_close_doc},
1308     {"execute", (PyCFunction)psyco_curs_execute,
1309      METH_VARARGS|METH_KEYWORDS, psyco_curs_execute_doc},
1310     {"executemany", (PyCFunction)psyco_curs_executemany,
1311      METH_VARARGS|METH_KEYWORDS, psyco_curs_executemany_doc},
1312     {"fetchone", (PyCFunction)psyco_curs_fetchone,
1313      METH_VARARGS, psyco_curs_fetchone_doc},
1314     {"fetchmany", (PyCFunction)psyco_curs_fetchmany,
1315      METH_VARARGS|METH_KEYWORDS, psyco_curs_fetchmany_doc},
1316     {"fetchall", (PyCFunction)psyco_curs_fetchall,
1317      METH_VARARGS, psyco_curs_fetchall_doc},
1318     {"callproc", (PyCFunction)psyco_curs_callproc,
1319      METH_VARARGS, psyco_curs_callproc_doc},
1320     {"nextset", (PyCFunction)psyco_curs_nextset,
1321      METH_VARARGS, psyco_curs_nextset_doc},
1322     {"setinputsizes", (PyCFunction)psyco_curs_setinputsizes,
1323      METH_VARARGS, psyco_curs_setinputsizes_doc},
1324     {"setoutputsize", (PyCFunction)psyco_curs_setoutputsize,
1325      METH_VARARGS, psyco_curs_setoutputsize_doc},
1326     /* DBAPI-2.0 extensions */
1327     {"scroll", (PyCFunction)psyco_curs_scroll,
1328      METH_VARARGS|METH_KEYWORDS, psyco_curs_scroll_doc},
1329     /* psycopg extensions */
1330 #ifdef PSYCOPG_EXTENSIONS
1331     {"mogrify", (PyCFunction)psyco_curs_mogrify,
1332      METH_VARARGS|METH_KEYWORDS, psyco_curs_mogrify_doc},
1333     {"fileno", (PyCFunction)psyco_curs_fileno,
1334      METH_VARARGS, psyco_curs_fileno_doc},
1335     {"isready", (PyCFunction)psyco_curs_isready,
1336      METH_VARARGS, psyco_curs_isready_doc},
1337     {"copy_from", (PyCFunction)psyco_curs_copy_from,
1338      METH_VARARGS|METH_KEYWORDS, psyco_curs_copy_from_doc},
1339     {"copy_to", (PyCFunction)psyco_curs_copy_to,
1340      METH_VARARGS|METH_KEYWORDS, psyco_curs_copy_to_doc},
1341 #endif
1342     {NULL}
1343 };
1344
1345 /* object member list */
1346
1347 #define OFFSETOF(x) offsetof(cursorObject, x)
1348
1349 static struct PyMemberDef cursorObject_members[] = {
1350     /* DBAPI-2.0 basics */
1351     {"rowcount", T_LONG, OFFSETOF(rowcount), RO,
1352         "Number of rows read from the backend in the last command."},
1353     {"arraysize", T_LONG, OFFSETOF(arraysize), 0, 
1354         "Number of records `fetchmany()` must fetch if not explicitely " \
1355         "specified."},
1356     {"description", T_OBJECT, OFFSETOF(description), RO,
1357         "Cursor description as defined in DBAPI-2.0."},
1358     {"lastrowid", T_LONG, OFFSETOF(lastoid), RO,
1359         "The ``oid`` of the last row inserted by the cursor."},
1360     /* DBAPI-2.0 extensions */
1361     {"rownumber", T_LONG, OFFSETOF(row), RO,
1362         "The current row position."},
1363     {"connection", T_OBJECT, OFFSETOF(conn), RO, 
1364         "The connection where the cursor comes from."},
1365 #ifdef PSYCOPG_EXTENSIONS
1366     {"name", T_STRING, OFFSETOF(name), RO},
1367     {"statusmessage", T_OBJECT, OFFSETOF(pgstatus), RO,
1368         "The return message of the last command."},
1369     {"query", T_OBJECT, OFFSETOF(query), RO,
1370         "The last query text sent to the backend."},
1371     {"row_factory", T_OBJECT, OFFSETOF(tuple_factory), 0},
1372     {"tzinfo_factory", T_OBJECT, OFFSETOF(tzinfo_factory), 0},
1373     {"typecaster", T_OBJECT, OFFSETOF(caster), RO},
1374     {"string_types", T_OBJECT, OFFSETOF(string_types), 0},
1375     {"binary_types", T_OBJECT, OFFSETOF(binary_types), 0},
1376 #endif
1377     {NULL}
1378 };
1379
1380 /* initialization and finalization methods */
1381
1382 static int
1383 cursor_setup(cursorObject *self, connectionObject *conn, char *name)
1384 {
1385     Dprintf("cursor_setup: init cursor object at %p", self);
1386     Dprintf("cursor_setup:     parameters: name = %s, conn = %p", name, conn);
1387     
1388     if (name) {
1389         self->name = PyMem_Malloc(strlen(name)+1);
1390         if (self->name == NULL) return 1;
1391         strncpy(self->name, name, strlen(name)+1);
1392     }
1393
1394     /* FIXME: why does this raise an excpetion on the _next_ line of code?
1395     if (PyObject_IsInstance((PyObject*)conn,
1396                              (PyObject *)&connectionType) == 0) {
1397         PyErr_SetString(PyExc_TypeError,
1398             "argument 1 must be subclass of psycopg2._psycopg.connection");
1399         return 1;
1400     } */
1401     self->conn = conn;
1402     Py_INCREF((PyObject*)self->conn);
1403     
1404     self->closed = 0;
1405     self->mark = conn->mark;
1406     self->pgres = NULL; 
1407     self->notuples = 1;
1408     self->arraysize = 1;
1409     self->rowcount = -1;
1410     self->lastoid = InvalidOid;
1411     
1412     self->casts = NULL;
1413     self->notice = NULL;
1414     
1415     self->string_types = NULL;
1416     self->binary_types = NULL;
1417     
1418     self->description = Py_None;
1419     Py_INCREF(Py_None);
1420     self->pgstatus = Py_None;
1421     Py_INCREF(Py_None);
1422     self->tuple_factory = Py_None;
1423     Py_INCREF(Py_None);
1424     self->query = Py_None;
1425     Py_INCREF(Py_None);
1426     
1427     /* default tzinfo factory */
1428     self->tzinfo_factory = pyPsycopgTzFixedOffsetTimezone;
1429     Py_INCREF(self->tzinfo_factory);
1430     
1431     Dprintf("cursor_setup: good cursor object at %p, refcnt = %d",
1432             self, ((PyObject *)self)->ob_refcnt);
1433     return 0;
1434 }
1435
1436 static void
1437 cursor_dealloc(PyObject* obj)
1438 {
1439     cursorObject *self = (cursorObject *)obj;
1440
1441     if (self->name) PyMem_Free(self->name);
1442     
1443     Py_XDECREF((PyObject*)self->conn);
1444     Py_XDECREF(self->casts);
1445     Py_XDECREF(self->description);
1446     Py_XDECREF(self->pgstatus);
1447     Py_XDECREF(self->tuple_factory);
1448     Py_XDECREF(self->tzinfo_factory);
1449     Py_XDECREF(self->query);
1450
1451     IFCLEARPGRES(self->pgres);
1452     
1453     Dprintf("cursor_dealloc: deleted cursor object at %p, refcnt = %d",
1454             obj, obj->ob_refcnt);
1455
1456     obj->ob_type->tp_free(obj);
1457 }
1458
1459 static int
1460 cursor_init(PyObject *obj, PyObject *args, PyObject *kwds)
1461 {
1462     char *name = NULL;
1463     PyObject *conn;
1464     
1465     if (!PyArg_ParseTuple(args, "O|s", &conn, &name))
1466         return -1;
1467
1468     return cursor_setup((cursorObject *)obj, (connectionObject *)conn, name);
1469 }
1470
1471 static PyObject *
1472 cursor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1473 {
1474     return type->tp_alloc(type, 0);
1475 }
1476
1477 static void
1478 cursor_del(PyObject* self)
1479 {
1480     PyObject_Del(self);
1481 }
1482
1483 static PyObject *
1484 cursor_repr(cursorObject *self)
1485 {
1486     return PyString_FromFormat(
1487         "<cursor object at %p; closed: %d>", self, self->closed);
1488 }
1489
1490
1491 /* object type */
1492
1493 #define cursorType_doc \
1494 "A database cursor."
1495
1496 PyTypeObject cursorType = {
1497     PyObject_HEAD_INIT(NULL)
1498     0,
1499     "psycopg2._psycopg.cursor",
1500     sizeof(cursorObject),
1501     0,
1502     cursor_dealloc, /*tp_dealloc*/
1503     0,          /*tp_print*/  
1504     0,          /*tp_getattr*/
1505     0,          /*tp_setattr*/
1506     0,          /*tp_compare*/
1507     (reprfunc)cursor_repr, /*tp_repr*/
1508     0,          /*tp_as_number*/
1509     0,          /*tp_as_sequence*/
1510     0,          /*tp_as_mapping*/
1511     0,          /*tp_hash */
1512
1513     0,          /*tp_call*/
1514     (reprfunc)cursor_repr, /*tp_str*/
1515     0,          /*tp_getattro*/
1516     0,          /*tp_setattro*/
1517     0,          /*tp_as_buffer*/
1518
1519     Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
1520     cursorType_doc, /*tp_doc*/
1521     
1522     0,          /*tp_traverse*/
1523     0,          /*tp_clear*/
1524
1525     0,          /*tp_richcompare*/
1526     0,          /*tp_weaklistoffset*/
1527
1528     cursor_iter, /*tp_iter*/
1529     cursor_next, /*tp_iternext*/
1530
1531     /* Attribute descriptor and subclassing stuff */
1532
1533     cursorObject_methods, /*tp_methods*/
1534     cursorObject_members, /*tp_members*/
1535     0,          /*tp_getset*/
1536     0,          /*tp_base*/
1537     0,          /*tp_dict*/
1538     
1539     0,          /*tp_descr_get*/
1540     0,          /*tp_descr_set*/
1541     0,          /*tp_dictoffset*/
1542     
1543     cursor_init, /*tp_init*/
1544     0, /*tp_alloc  Will be set to PyType_GenericAlloc in module init*/
1545     cursor_new, /*tp_new*/
1546     (freefunc)cursor_del, /*tp_free  Low-level free-memory routine */
1547     0,          /*tp_is_gc For PyObject_IS_GC */
1548     0,          /*tp_bases*/
1549     0,          /*tp_mro method resolution order */
1550     0,          /*tp_cache*/
1551     0,          /*tp_subclasses*/
1552     0           /*tp_weaklist*/
1553 };