1 /* cursor_type.c - python interface to cursor objects
3 * Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
5 * This file is part of psycopg.
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.
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.
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.
23 #include <structmember.h>
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"
38 extern PyObject *pyPsycopgTzFixedOffsetTimezone;
43 /* close method - close the cursor */
45 #define psyco_curs_close_doc \
46 "close() -- Close the cursor."
49 psyco_curs_close(cursorObject *self, PyObject *args)
51 if (!PyArg_ParseTuple(args, "")) return NULL;
53 EXC_IF_CURS_CLOSED(self);
55 if (self->name != NULL) {
59 PyOS_snprintf(buffer, 127, "CLOSE %s", self->name);
60 if (pq_execute(self, buffer, 0) == -1) return NULL;
64 Dprintf("psyco_curs_close: cursor at %p closed", self);
71 /* execute method - executes a query */
73 /* mogrify a query string and build argument array or dict */
76 _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
78 PyObject *key, *value, *n, *item;
80 int index = 0, force = 0;
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 */
86 c = PyString_AsString(fmt);
89 /* handle plain percent symbol in format string */
90 if (c[0] == '%' && c[1] == '%') {
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
100 else if (c[0] == '%' && c[1] == '(') {
102 /* let's have d point the end of the argument */
103 for (d = c + 2; *d && *d != ')'; 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 */
110 /* if value is NULL we did not find the key (or this is not a
111 dictionary): let python raise a KeyError */
113 Py_DECREF(key); /* destroy key */
114 Py_XDECREF(n); /* destroy n */
118 Dprintf("_mogrify: value refcnt: %d (+1)", value->ob_refcnt);
124 if ((item = PyObject_GetItem(n, key)) == NULL) {
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 */
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
141 while (*d && !isalpha(*d)) d++;
145 t = microprotocol_getquoted(value, conn);
148 PyDict_SetItem(n, key, t);
149 /* both key and t refcnt +1, key is at 2 now */
152 /* no adapter found, raise a BIG exception */
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 */
165 /* we have an item with one extra refcnt here, zap! */
168 Py_DECREF(key); /* key has the original refcnt now */
169 Dprintf("_mogrify: after value refcnt: %d",value->ob_refcnt);
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
179 value = PySequence_GetItem(var, index);
180 /* value has refcnt inc'ed by 1 here */
182 /* if value is NULL this is not a sequence or the index is wrong;
183 anyway we let python set its own exception */
190 n = PyTuple_New(PyObject_Length(var));
193 /* let's have d point just after the '%' */
196 if (value == Py_None) {
197 PyTuple_SET_ITEM(n, index, PyString_FromString("NULL"));
198 while (*d && !isalpha(*d)) d++;
203 PyObject *t = microprotocol_getquoted(value, conn);
206 PyTuple_SET_ITEM(n, index, t);
223 if (force && n == NULL)
230 #define psyco_curs_execute_doc \
231 "execute(query, vars=None, async=0) -- Execute query with bound vars."
234 _psyco_curs_execute(cursorObject *self,
235 PyObject *operation, PyObject *vars, long int async)
238 PyObject *fquery, *cvt = NULL, *uoperation = NULL;
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);
248 pthread_mutex_unlock(&(self->conn->lock));
250 if (!PyObject_IsTrue(operation)) {
251 psyco_set_error(ProgrammingError, (PyObject*)self,
252 "can't execute an empty query", NULL, NULL);
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 */
262 operation = PyUnicode_AsEncodedString(
263 operation, PyString_AsString(enc), NULL);
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;
269 /* we clone operation in uoperation to be sure to free it later */
270 uoperation = operation;
273 PyErr_Format(InterfaceError, "can't encode unicode query to %s",
274 self->conn->encoding);
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");
285 IFCLEARPGRES(self->pgres);
288 Py_DECREF(self->query);
292 Dprintf("psyco_curs_execute: starting execution of new query");
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) */
298 if (vars && vars != Py_None)
300 if(_mogrify(vars, operation, self->conn, &cvt) == -1) {
301 Py_XDECREF(uoperation);
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
311 "not enough arguments for format string"
312 "not all arguments converted"
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.) */
318 if (!(fquery = PyString_Format(operation, cvt))) {
319 PyObject *err, *arg, *trace;
322 PyErr_Fetch(&err, &arg, &trace);
324 if (err && PyErr_GivenExceptionMatches(err, PyExc_TypeError)) {
325 Dprintf("psyco_curs_execute: TypeError exception catched");
326 PyErr_NormalizeException(&err, &arg, &trace);
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);
333 Dprintf("psyco_curs_execute: -> %s", s);
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,
348 /* if we did not manage our own exception, restore old one */
350 Py_XDECREF(err); Py_XDECREF(arg); Py_XDECREF(trace);
353 PyErr_Restore(err, arg, trace);
355 Py_XDECREF(uoperation);
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));
366 self->query = fquery;
369 Dprintf("psyco_curs_execute: cvt->refcnt = %d", cvt->ob_refcnt);
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));
379 Py_INCREF(operation);
380 self->query = operation;
384 res = pq_execute(self, PyString_AS_STRING(self->query), async);
386 Dprintf("psyco_curs_execute: res = %d, pgres = %p", res, self->pgres);
388 Py_XDECREF(uoperation);
390 return res == -1 ? 0 : 1;
394 psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
397 PyObject *vars = NULL, *operation = NULL;
399 static char *kwlist[] = {"query", "vars", "async", NULL};
401 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi", kwlist,
402 &operation, &vars, &async)) {
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",
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);
418 if (self->conn->mark != self->mark) {
419 psyco_set_error(ProgrammingError, (PyObject*)self,
420 "named cursor isn't valid anymore", NULL, NULL);
425 EXC_IF_CURS_CLOSED(self);
427 if (_psyco_curs_execute(self, operation, vars, async)) {
436 #define psyco_curs_executemany_doc \
437 "executemany(query, vars_list) -- Execute many queries with bound vars."
440 psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
442 PyObject *operation = NULL, *vars = NULL;
443 PyObject *v, *iter = NULL;
445 static char *kwlist[] = {"query", "vars_list", NULL};
447 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist,
448 &operation, &vars)) {
452 EXC_IF_CURS_CLOSED(self);
454 if (self->name != NULL) {
455 psyco_set_error(ProgrammingError, (PyObject*)self,
456 "can't call .executemany() on named cursors", NULL, NULL);
460 if (!PyIter_Check(vars)) {
461 vars = iter = PyObject_GetIter(vars);
462 if (iter == NULL) return NULL;
465 while ((v = PyIter_Next(vars)) != NULL) {
466 if (_psyco_curs_execute(self, operation, v, 0) == 0) {
481 #ifdef PSYCOPG_EXTENSIONS
482 #define psyco_curs_mogrify_doc \
483 "mogrify(query, vars=None) -> str -- Return query after vars binding."
486 psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs)
488 PyObject *vars = NULL, *cvt = NULL, *operation = NULL;
491 static char *kwlist[] = {"query", "vars", NULL};
493 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist,
494 &operation, &vars)) {
498 if (PyUnicode_Check(operation)) {
499 PyErr_SetString(NotSupportedError,
500 "unicode queries not yet supported");
504 EXC_IF_CURS_CLOSED(self);
505 IFCLEARPGRES(self->pgres);
507 /* note that we don't overwrite the last query executed on the cursor, we
508 just *return* the new query with bound variables
510 TODO: refactor the common mogrification code (see psycopg_curs_execute
511 for comments, the code is amost identical) */
515 if(_mogrify(vars, operation, self->conn, &cvt) == -1) return NULL;
519 if (!(fquery = PyString_Format(operation, cvt))) {
520 PyObject *err, *arg, *trace;
523 PyErr_Fetch(&err, &arg, &trace);
525 if (err && PyErr_GivenExceptionMatches(err, PyExc_TypeError)) {
526 Dprintf("psyco_curs_execute: TypeError exception catched");
527 PyErr_NormalizeException(&err, &arg, &trace);
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);
534 Dprintf("psyco_curs_execute: -> %s", s);
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,
549 /* if we did not manage our own exception, restore old one */
551 Py_XDECREF(err); Py_XDECREF(arg); Py_XDECREF(trace);
554 PyErr_Restore(err, arg, trace);
559 Dprintf("psyco_curs_execute: cvt->refcnt = %d, fquery->refcnt = %d",
560 cvt->ob_refcnt, fquery->ob_refcnt);
565 Py_INCREF(operation);
573 /* fetchone method - fetch one row of results */
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"
582 _psyco_curs_prefetch(cursorObject *self)
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);
596 pthread_mutex_unlock(&(self->conn->lock));
598 if (self->pgres == NULL || self->needsfetch) {
599 self->needsfetch = 0;
600 Dprintf("_psyco_curs_prefetch: trying to fetch data");
603 Dprintf("_psycopg_curs_prefetch: result = %d", i);
607 Dprintf("_psyco_curs_prefetch: result = %d", i);
612 _psyco_curs_buildrow_fill(cursorObject *self, PyObject *res,
613 int row, int n, int istuple)
619 for (i=0; i < n; i++) {
620 if (PQgetisnull(self->pgres, row, i)) {
625 str = (unsigned char*)PQgetvalue(self->pgres, row, i);
626 len = PQgetlength(self->pgres, row, i);
629 Dprintf("_psyco_curs_buildrow: row %ld, element %d, len %i",
632 val = typecast_cast(PyTuple_GET_ITEM(self->casts, i), (char*)str, len,
636 Dprintf("_psyco_curs_buildrow: val->refcnt = %d", val->ob_refcnt);
638 PyTuple_SET_ITEM(res, i, val);
641 PySequence_SetItem(res, i, val);
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 */
658 _psyco_curs_buildrow(cursorObject *self, int row)
662 n = PQnfields(self->pgres);
663 return _psyco_curs_buildrow_fill(self, PyTuple_New(n), row, n, 1);
667 _psyco_curs_buildrow_with_factory(cursorObject *self, int row)
672 n = PQnfields(self->pgres);
673 if ((res = PyObject_CallFunction(self->tuple_factory, "O", self))== NULL)
676 return _psyco_curs_buildrow_fill(self, res, row, n, 0);
680 psyco_curs_fetchone(cursorObject *self, PyObject *args)
684 if (args && !PyArg_ParseTuple(args, "")) return NULL;
686 EXC_IF_CURS_CLOSED(self)
687 if (_psyco_curs_prefetch(self) < 0) return NULL;
688 EXC_IF_NO_TUPLES(self);
690 if (self->name != NULL) {
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;
699 Dprintf("psyco_curs_fetchone: fetching row %ld", self->row);
700 Dprintf("psyco_curs_fetchone: rowcount = %ld", self->rowcount);
702 if (self->row >= self->rowcount) {
703 /* we exausted available data: return None */
708 if (self->tuple_factory == Py_None)
709 res = _psyco_curs_buildrow(self, self->row);
711 res = _psyco_curs_buildrow_with_factory(self, self->row);
713 self->row++; /* move the counter to next line */
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);
725 /* fetch many - fetch some results */
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"
734 psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
737 PyObject *list, *res;
739 long int size = self->arraysize;
740 static char *kwlist[] = {"size", NULL};
742 if (!PyArg_ParseTupleAndKeywords(args, kwords, "|l", kwlist, &size)) {
746 EXC_IF_CURS_CLOSED(self);
747 if (_psyco_curs_prefetch(self) < 0) return NULL;
748 EXC_IF_NO_TUPLES(self);
750 if (self->name != NULL) {
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;
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;
765 Dprintf("psyco_curs_fetchmany: size = %ld", size);
768 return PyList_New(0);
771 list = PyList_New(size);
773 for (i = 0; i < size; i++) {
774 if (self->tuple_factory == Py_None)
775 res = _psyco_curs_buildrow(self, self->row);
777 res = _psyco_curs_buildrow_with_factory(self, self->row);
786 PyList_SET_ITEM(list, i, res);
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);
799 /* fetch all - fetch all results */
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"
809 psyco_curs_fetchall(cursorObject *self, PyObject *args)
812 PyObject *list, *res;
814 if (!PyArg_ParseTuple(args, "")) {
818 EXC_IF_CURS_CLOSED(self);
819 if (_psyco_curs_prefetch(self) < 0) return NULL;
820 EXC_IF_NO_TUPLES(self);
822 if (self->name != NULL) {
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;
831 size = self->rowcount - self->row;
834 return PyList_New(0);
837 list = PyList_New(size);
839 for (i = 0; i < size; i++) {
840 if (self->tuple_factory == Py_None)
841 res = _psyco_curs_buildrow(self, self->row);
843 res = _psyco_curs_buildrow_with_factory(self, self->row);
852 PyList_SET_ITEM(list, i, res);
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);
865 /* callproc method - execute a stored procedure */
867 #define psyco_curs_callproc_doc \
868 "callproc(procname, parameters=None, async=0) -- Execute stored procedure."
871 psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
873 char *procname = NULL, *sql = NULL;
875 int i, nparameters = 0, sl = 0;
876 PyObject *parameters = NULL;
877 PyObject *operation = NULL;
878 PyObject *res = NULL;
880 if (!PyArg_ParseTuple(args, "s|Oi", &procname, ¶meters, &async)) {
884 EXC_IF_CURS_CLOSED(self);
886 if (self->name != NULL) {
887 psyco_set_error(ProgrammingError, (PyObject*)self,
888 "can't call .callproc() on named cursors", NULL, NULL);
892 if(parameters && parameters != Py_None) {
893 nparameters = PyObject_Length(parameters);
894 if (nparameters < 0) nparameters = 0;
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;
902 sprintf(sql, "SELECT %s(", procname);
903 for(i=0; i<nparameters; i++) {
909 operation = PyString_FromString(sql);
910 PyMem_Free((void*)sql);
912 if (_psyco_curs_execute(self, operation, parameters, async)) {
917 Py_DECREF(operation);
922 /* nextset method - return the next set of data (not supported) */
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."
930 psyco_curs_nextset(cursorObject *self, PyObject *args)
932 if (!PyArg_ParseTuple(args, "")) return NULL;
934 EXC_IF_CURS_CLOSED(self);
936 PyErr_SetString(NotSupportedError, "not supported by PostgreSQL");
941 /* setinputsizes - predefine memory areas for execute (does nothing) */
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."
948 psyco_curs_setinputsizes(cursorObject *self, PyObject *args)
952 if (!PyArg_ParseTuple(args, "O", &sizes))
955 EXC_IF_CURS_CLOSED(self);
962 /* setoutputsize - predefine memory areas for execute (does nothing) */
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."
969 psyco_curs_setoutputsize(cursorObject *self, PyObject *args)
971 long int size, column;
973 if (!PyArg_ParseTuple(args, "l|l", &size, &column))
976 EXC_IF_CURS_CLOSED(self);
983 /* scroll - scroll position in result list */
985 #define psyco_curs_scroll_doc \
986 "scroll(value, mode='relative') -- Scroll to new position according to mode."
989 psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
992 char *mode = "relative";
994 static char *kwlist[] = {"value", "mode", NULL};
996 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|s",
997 kwlist, &value, &mode))
1000 EXC_IF_CURS_CLOSED(self);
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) {
1011 psyco_set_error(ProgrammingError, (PyObject*)self,
1012 "scroll mode must be 'relative' or 'absolute'", NULL, NULL);
1016 if (newpos < 0 || newpos >= self->rowcount ) {
1017 psyco_set_error(ProgrammingError, (PyObject*)self,
1018 "scroll destination out of bounds", NULL, NULL);
1028 EXC_IF_NO_MARK(self);
1030 if (strcmp(mode, "absolute") == 0) {
1031 PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM %s",
1035 PyOS_snprintf(buffer, 127, "MOVE %d FROM %s", value, self->name);
1037 if (pq_execute(self, buffer, 0) == -1) return NULL;
1038 if (_psyco_curs_prefetch(self) < 0) return NULL;
1046 #ifdef PSYCOPG_EXTENSIONS
1048 /* extension: copy_from - implements COPY FROM */
1050 #define psyco_curs_copy_from_doc \
1051 "copy_from(file, table, sep='\\t', null='\\N', columns=None) -- Copy table from file."
1054 _psyco_curs_has_read_check(PyObject* o, void* var)
1056 if (PyObject_HasAttrString(o, "readline")
1057 && PyObject_HasAttrString(o, "read")) {
1059 *((PyObject**)var) = o;
1063 PyErr_SetString(PyExc_TypeError,
1064 "argument 1 must have both .read() and .readline() methods");
1070 psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
1074 char *sep = "\t", *null = NULL;
1075 long int bufsize = DEFAULT_COPYSIZE;
1076 PyObject *file, *columns = NULL, *res = NULL;
1077 char columnlist[1024] = "";
1079 static char *kwlist[] = {"file", "table", "sep", "null", "size",
1082 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ssiO", kwlist,
1083 _psyco_curs_has_read_check, &file,
1084 &table_name, &sep, &null, &bufsize,
1089 if (columns != NULL && columns != Py_None) {
1090 PyObject* collistiter = PyObject_GetIter(columns);
1095 if (collistiter == NULL) {
1098 strcpy(columnlist, " (");
1099 while ((col = PyIter_Next(collistiter)) != NULL) {
1100 if (!PyString_Check(col)) {
1102 Py_DECREF(collistiter);
1103 PyErr_SetString(PyExc_ValueError,
1104 "Elements in column list must be strings");
1107 PyString_AsStringAndSize(col, &colname, &colitemlen);
1108 if (collistlen + colitemlen > 1022) {
1110 Py_DECREF(collistiter);
1111 PyErr_SetString(PyExc_ValueError, "Column list too long");
1114 strncpy(&columnlist[collistlen], colname, colitemlen);
1115 collistlen += colitemlen;
1116 columnlist[collistlen++] = ',';
1119 Py_DECREF(collistiter);
1121 if (collistlen == 2) { /* empty list; we printed no comma */
1125 columnlist[collistlen - 1] = ')';
1126 columnlist[collistlen] = '\0';
1129 if (PyErr_Occurred()) {
1133 EXC_IF_CURS_CLOSED(self);
1136 PyOS_snprintf(query, 1023, "COPY %s%s FROM stdin USING DELIMITERS '%s'"
1137 " WITH NULL AS '%s'", table_name, columnlist, sep, null);
1140 PyOS_snprintf(query, 1023, "COPY %s%s FROM stdin USING DELIMITERS '%s'",
1141 table_name, columnlist, sep);
1143 Dprintf("psyco_curs_copy_from: query = %s", query);
1145 self->copysize = bufsize;
1146 self->copyfile = file;
1148 if (pq_execute(self, query, 0) == 1) {
1153 self->copyfile =NULL;
1158 #define psyco_curs_copy_to_doc \
1159 "copy_to(file, table, sep='\\t', null='\\N') -- Copy table to file."
1162 _psyco_curs_has_write_check(PyObject* o, void* var)
1164 if (PyObject_HasAttrString(o, "write")) {
1166 *((PyObject**)var) = o;
1170 PyErr_SetString(PyExc_TypeError,
1171 "argument 1 must have a .write() method");
1177 psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
1181 char *sep = "\t", *null = NULL;
1182 PyObject *file, *res = NULL;
1184 static char *kwlist[] = {"file", "table", "sep", "null", NULL};
1186 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ss", kwlist,
1187 _psyco_curs_has_write_check, &file,
1188 &table_name, &sep, &null)) {
1192 EXC_IF_CURS_CLOSED(self);
1195 PyOS_snprintf(query, 255, "COPY %s TO stdout USING DELIMITERS '%s'"
1196 " WITH NULL AS '%s'", table_name, sep, null);
1199 PyOS_snprintf(query, 255, "COPY %s TO stdout USING DELIMITERS '%s'",
1204 self->copyfile = file;
1206 if (pq_execute(self, query, 0) == 1) {
1211 self->copyfile = NULL;
1215 /* extension: fileno - return the file descripor of the connection */
1217 #define psyco_curs_fileno_doc \
1218 "fileno() -> int -- Return file descriptor associated to database connection."
1221 psyco_curs_fileno(cursorObject *self, PyObject *args)
1225 if (!PyArg_ParseTuple(args, "")) return NULL;
1226 EXC_IF_CURS_CLOSED(self);
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));
1237 return PyInt_FromLong(socket);
1240 /* extension: isready - return true if data from async execute is ready */
1242 #define psyco_curs_isready_doc \
1243 "isready() -> bool -- Return True if data is ready after an async query."
1246 psyco_curs_isready(cursorObject *self, PyObject *args)
1248 if (!PyArg_ParseTuple(args, "")) return NULL;
1249 EXC_IF_CURS_CLOSED(self);
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. */
1255 if (pq_is_busy(self->conn)) {
1256 Py_INCREF(Py_False);
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;
1274 /** the cursor object **/
1276 /* iterator protocol */
1279 cursor_iter(PyObject *self)
1281 EXC_IF_CURS_CLOSED((cursorObject*)self);
1287 cursor_next(PyObject *self)
1291 /* we don't parse arguments: psyco_curs_fetchone will do that for us */
1292 res = psyco_curs_fetchone((cursorObject*)self, NULL);
1294 /* convert a None to NULL to signal the end of iteration */
1295 if (res && res == Py_None) {
1302 /* object method list */
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},
1345 /* object member list */
1347 #define OFFSETOF(x) offsetof(cursorObject, x)
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 " \
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},
1380 /* initialization and finalization methods */
1383 cursor_setup(cursorObject *self, connectionObject *conn, char *name)
1385 Dprintf("cursor_setup: init cursor object at %p", self);
1386 Dprintf("cursor_setup: parameters: name = %s, conn = %p", name, conn);
1389 self->name = PyMem_Malloc(strlen(name)+1);
1390 if (self->name == NULL) return 1;
1391 strncpy(self->name, name, strlen(name)+1);
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");
1402 Py_INCREF((PyObject*)self->conn);
1405 self->mark = conn->mark;
1408 self->arraysize = 1;
1409 self->rowcount = -1;
1410 self->lastoid = InvalidOid;
1413 self->notice = NULL;
1415 self->string_types = NULL;
1416 self->binary_types = NULL;
1418 self->description = Py_None;
1420 self->pgstatus = Py_None;
1422 self->tuple_factory = Py_None;
1424 self->query = Py_None;
1427 /* default tzinfo factory */
1428 self->tzinfo_factory = pyPsycopgTzFixedOffsetTimezone;
1429 Py_INCREF(self->tzinfo_factory);
1431 Dprintf("cursor_setup: good cursor object at %p, refcnt = %d",
1432 self, ((PyObject *)self)->ob_refcnt);
1437 cursor_dealloc(PyObject* obj)
1439 cursorObject *self = (cursorObject *)obj;
1441 if (self->name) PyMem_Free(self->name);
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);
1451 IFCLEARPGRES(self->pgres);
1453 Dprintf("cursor_dealloc: deleted cursor object at %p, refcnt = %d",
1454 obj, obj->ob_refcnt);
1456 obj->ob_type->tp_free(obj);
1460 cursor_init(PyObject *obj, PyObject *args, PyObject *kwds)
1465 if (!PyArg_ParseTuple(args, "O|s", &conn, &name))
1468 return cursor_setup((cursorObject *)obj, (connectionObject *)conn, name);
1472 cursor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1474 return type->tp_alloc(type, 0);
1478 cursor_del(PyObject* self)
1484 cursor_repr(cursorObject *self)
1486 return PyString_FromFormat(
1487 "<cursor object at %p; closed: %d>", self, self->closed);
1493 #define cursorType_doc \
1494 "A database cursor."
1496 PyTypeObject cursorType = {
1497 PyObject_HEAD_INIT(NULL)
1499 "psycopg2._psycopg.cursor",
1500 sizeof(cursorObject),
1502 cursor_dealloc, /*tp_dealloc*/
1507 (reprfunc)cursor_repr, /*tp_repr*/
1509 0, /*tp_as_sequence*/
1510 0, /*tp_as_mapping*/
1514 (reprfunc)cursor_repr, /*tp_str*/
1519 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
1520 cursorType_doc, /*tp_doc*/
1525 0, /*tp_richcompare*/
1526 0, /*tp_weaklistoffset*/
1528 cursor_iter, /*tp_iter*/
1529 cursor_next, /*tp_iternext*/
1531 /* Attribute descriptor and subclassing stuff */
1533 cursorObject_methods, /*tp_methods*/
1534 cursorObject_members, /*tp_members*/
1541 0, /*tp_dictoffset*/
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 */
1549 0, /*tp_mro method resolution order */
1551 0, /*tp_subclasses*/