Fixed both Python 2.5 and 64 bit problems.

This commit is contained in:
Federico Di Gregorio 2007-04-10 06:36:18 +00:00
parent fadd1a6938
commit e5829292cd
37 changed files with 887 additions and 753 deletions

View File

@ -1,3 +1,8 @@
2007-04-10 Federico Di Gregorio <fog@initd.org>
* Applied super-patch from David Rushby to fix Python 2.5 and 64
bit problems (all of them, kudos!)
2007-02-22 Federico Di Gregorio <fog@initd.org> 2007-02-22 Federico Di Gregorio <fog@initd.org>
* Added support for per-connection and per-cursor typecasters. * Added support for per-connection and per-cursor typecasters.

View File

@ -6,8 +6,8 @@ recursive-include psycopg2da *
recursive-include examples *.py somehackers.jpg whereareyou.jpg recursive-include examples *.py somehackers.jpg whereareyou.jpg
recursive-include debian * recursive-include debian *
recursive-include doc TODO HACKING SUCCESS ChangeLog-1.x async.txt recursive-include doc TODO HACKING SUCCESS ChangeLog-1.x async.txt
recursive-include doc *.rst *.css *.html
recursive-include scripts *.py *.sh recursive-include scripts *.py *.sh
include scripts/maketypes.sh scripts/buildtypes.py include scripts/maketypes.sh scripts/buildtypes.py
include AUTHORS README INSTALL LICENSE ChangeLog include AUTHORS README INSTALL LICENSE ChangeLog
include PKG-INFO MANIFEST.in MANIFEST setup.py setup.cfg include PKG-INFO MANIFEST.in MANIFEST setup.py setup.cfg
recursive-include doc *.rst *.css *.html

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <stringobject.h> #include <stringobject.h>
@ -55,14 +56,14 @@ PyObject *
asis_conform(asisObject *self, PyObject *args) asis_conform(asisObject *self, PyObject *args)
{ {
PyObject *res, *proto; PyObject *res, *proto;
if (!PyArg_ParseTuple(args, "O", &proto)) return NULL; if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
if (proto == (PyObject*)&isqlquoteType) if (proto == (PyObject*)&isqlquoteType)
res = (PyObject*)self; res = (PyObject*)self;
else else
res = Py_None; res = Py_None;
Py_INCREF(res); Py_INCREF(res);
return res; return res;
} }
@ -90,14 +91,18 @@ static PyMethodDef asisObject_methods[] = {
static int static int
asis_setup(asisObject *self, PyObject *obj) asis_setup(asisObject *self, PyObject *obj)
{ {
Dprintf("asis_setup: init asis object at %p, refcnt = %d", Dprintf("asis_setup: init asis object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
self->wrapped = obj; self->wrapped = obj;
Py_INCREF(self->wrapped); Py_INCREF(self->wrapped);
Dprintf("asis_setup: good asis object at %p, refcnt = %d", Dprintf("asis_setup: good asis object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
return 0; return 0;
} }
@ -107,10 +112,12 @@ asis_dealloc(PyObject* obj)
asisObject *self = (asisObject *)obj; asisObject *self = (asisObject *)obj;
Py_XDECREF(self->wrapped); Py_XDECREF(self->wrapped);
Dprintf("asis_dealloc: deleted asis object at %p, refcnt = %d", Dprintf("asis_dealloc: deleted asis object at %p, refcnt = "
obj, obj->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
obj, obj->ob_refcnt
);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -118,7 +125,7 @@ static int
asis_init(PyObject *obj, PyObject *args, PyObject *kwds) asis_init(PyObject *obj, PyObject *args, PyObject *kwds)
{ {
PyObject *o; PyObject *o;
if (!PyArg_ParseTuple(args, "O", &o)) if (!PyArg_ParseTuple(args, "O", &o))
return -1; return -1;
@ -127,7 +134,7 @@ asis_init(PyObject *obj, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
asis_new(PyTypeObject *type, PyObject *args, PyObject *kwds) asis_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
return type->tp_alloc(type, 0); return type->tp_alloc(type, 0);
} }
@ -159,7 +166,7 @@ PyTypeObject asisType = {
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
@ -171,14 +178,14 @@ PyTypeObject asisType = {
0, /*tp_call*/ 0, /*tp_call*/
(reprfunc)asis_str, /*tp_str*/ (reprfunc)asis_str, /*tp_str*/
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
asisType_doc, /*tp_doc*/ asisType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -195,11 +202,11 @@ PyTypeObject asisType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
asis_init, /*tp_init*/ asis_init, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
asis_new, /*tp_new*/ asis_new, /*tp_new*/
@ -219,9 +226,9 @@ PyObject *
psyco_AsIs(PyObject *module, PyObject *args) psyco_AsIs(PyObject *module, PyObject *args)
{ {
PyObject *obj; PyObject *obj;
if (!PyArg_ParseTuple(args, "O", &obj)) if (!PyArg_ParseTuple(args, "O", &obj))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&asisType, "O", obj); return PyObject_CallFunction((PyObject *)&asisType, "O", obj);
} }

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_ASIS_H #ifndef PSYCOPG_ASIS_H
#define PSYCOPG_ASIS_H 1 #define PSYCOPG_ASIS_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -39,7 +40,7 @@ typedef struct {
} asisObject; } asisObject;
/* functions exported to psycopgmodule.c */ /* functions exported to psycopgmodule.c */
extern PyObject *psyco_AsIs(PyObject *module, PyObject *args); extern PyObject *psyco_AsIs(PyObject *module, PyObject *args);
#define psyco_AsIs_doc \ #define psyco_AsIs_doc \
"AsIs(obj) -> new AsIs wrapper object" "AsIs(obj) -> new AsIs wrapper object"

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <stringobject.h> #include <stringobject.h>
@ -38,8 +39,8 @@
#ifndef PSYCOPG_OWN_QUOTING #ifndef PSYCOPG_OWN_QUOTING
static unsigned char * static unsigned char *
binary_escape(unsigned char *from, unsigned int from_length, binary_escape(unsigned char *from, size_t from_length,
unsigned int *to_length, PGconn *conn) size_t *to_length, PGconn *conn)
{ {
#if PG_MAJOR_VERSION > 8 || \ #if PG_MAJOR_VERSION > 8 || \
(PG_MAJOR_VERSION == 8 && PG_MINOR_VERSION > 1) || \ (PG_MAJOR_VERSION == 8 && PG_MINOR_VERSION > 1) || \
@ -52,11 +53,11 @@ binary_escape(unsigned char *from, unsigned int from_length,
} }
#else #else
static unsigned char * static unsigned char *
binary_escape(unsigned char *from, unsigned int from_length, binary_escape(unsigned char *from, size_t from_length,
unsigned int *to_length, PGconn *conn) size_t *to_length, PGconn *conn)
{ {
unsigneed char *quoted, *chptr, *newptr; unsigned char *quoted, *chptr, *newptr;
int i, space, new_space; size_t i, space, new_space;
space = from_length + 2; space = from_length + 2;
@ -67,7 +68,7 @@ binary_escape(unsigned char *from, unsigned int from_length,
chptr = quoted; chptr = quoted;
for (i=0; i < len; i++) { for (i = 0; i < from_length; i++) {
if (chptr - quoted > space - 6) { if (chptr - quoted > space - 6) {
new_space = space * ((space) / (i + 1)) + 2 + 6; new_space = space * ((space) / (i + 1)) + 2 + 6;
if (new_space - space < 1024) space += 1024; if (new_space - space < 1024) space += 1024;
@ -102,7 +103,7 @@ binary_escape(unsigned char *from, unsigned int from_length,
} }
else { else {
unsigned char c; unsigned char c;
/* escape to octal notation \nnn */ /* escape to octal notation \nnn */
*chptr++ = '\\'; *chptr++ = '\\';
*chptr++ = '\\'; *chptr++ = '\\';
@ -122,7 +123,7 @@ binary_escape(unsigned char *from, unsigned int from_length,
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
*to_size = chptr - quoted + 1; *to_length = chptr - quoted + 1;
return quoted; return quoted;
} }
#endif #endif
@ -142,26 +143,26 @@ binary_quote(binaryObject *self)
/* escape and build quoted buffer */ /* escape and build quoted buffer */
PyObject_AsCharBuffer(self->wrapped, &buffer, &buffer_len); PyObject_AsCharBuffer(self->wrapped, &buffer, &buffer_len);
to = (char *)binary_escape((unsigned char*)buffer, buffer_len, &len, to = (char *)binary_escape((unsigned char*)buffer, (size_t) buffer_len,
self->conn ? ((connectionObject*)self->conn)->pgconn : NULL); &len, self->conn ? ((connectionObject*)self->conn)->pgconn : NULL);
if (to == NULL) { if (to == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
return NULL; return NULL;
} }
if (len > 0) if (len > 0)
self->buffer = PyString_FromFormat("'%s'", to); self->buffer = PyString_FromFormat("'%s'", to);
else else
self->buffer = PyString_FromString("''"); self->buffer = PyString_FromString("''");
PQfreemem(to); PQfreemem(to);
} }
/* if the wrapped object is not a string or a buffer, this is an error */ /* if the wrapped object is not a string or a buffer, this is an error */
else { else {
PyErr_SetString(PyExc_TypeError, "can't escape non-string object"); PyErr_SetString(PyExc_TypeError, "can't escape non-string object");
return NULL; return NULL;
} }
return self->buffer; return self->buffer;
} }
@ -206,14 +207,14 @@ PyObject *
binary_conform(binaryObject *self, PyObject *args) binary_conform(binaryObject *self, PyObject *args)
{ {
PyObject *res, *proto; PyObject *res, *proto;
if (!PyArg_ParseTuple(args, "O", &proto)) return NULL; if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
if (proto == (PyObject*)&isqlquoteType) if (proto == (PyObject*)&isqlquoteType)
res = (PyObject*)self; res = (PyObject*)self;
else else
res = Py_None; res = Py_None;
Py_INCREF(res); Py_INCREF(res);
return res; return res;
} }
@ -244,16 +245,19 @@ static PyMethodDef binaryObject_methods[] = {
static int static int
binary_setup(binaryObject *self, PyObject *str) binary_setup(binaryObject *self, PyObject *str)
{ {
Dprintf("binary_setup: init binary object at %p, refcnt = %d", Dprintf("binary_setup: init binary object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
self->buffer = NULL; self->buffer = NULL;
self->conn = NULL; self->conn = NULL;
self->wrapped = str; self->wrapped = str;
Py_INCREF(self->wrapped); Py_INCREF(self->wrapped);
Dprintf("binary_setup: good binary object at %p, refcnt = %d", Dprintf("binary_setup: good binary object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt);
return 0; return 0;
} }
@ -265,10 +269,12 @@ binary_dealloc(PyObject* obj)
Py_XDECREF(self->wrapped); Py_XDECREF(self->wrapped);
Py_XDECREF(self->buffer); Py_XDECREF(self->buffer);
Py_XDECREF(self->conn); Py_XDECREF(self->conn);
Dprintf("binary_dealloc: deleted binary object at %p, refcnt = %d", Dprintf("binary_dealloc: deleted binary object at %p, refcnt = "
obj, obj->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
obj, obj->ob_refcnt
);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -276,7 +282,7 @@ static int
binary_init(PyObject *obj, PyObject *args, PyObject *kwds) binary_init(PyObject *obj, PyObject *args, PyObject *kwds)
{ {
PyObject *str; PyObject *str;
if (!PyArg_ParseTuple(args, "O", &str)) if (!PyArg_ParseTuple(args, "O", &str))
return -1; return -1;
@ -285,7 +291,7 @@ binary_init(PyObject *obj, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
binary_new(PyTypeObject *type, PyObject *args, PyObject *kwds) binary_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
return type->tp_alloc(type, 0); return type->tp_alloc(type, 0);
} }
@ -315,7 +321,7 @@ PyTypeObject binaryType = {
binary_dealloc, /*tp_dealloc*/ binary_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
(reprfunc)binary_repr, /*tp_repr*/ (reprfunc)binary_repr, /*tp_repr*/
@ -333,7 +339,7 @@ PyTypeObject binaryType = {
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
binaryType_doc, /*tp_doc*/ binaryType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -350,11 +356,11 @@ PyTypeObject binaryType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
binary_init, /*tp_init*/ binary_init, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
binary_new, /*tp_new*/ binary_new, /*tp_new*/
@ -374,9 +380,9 @@ PyObject *
psyco_Binary(PyObject *module, PyObject *args) psyco_Binary(PyObject *module, PyObject *args)
{ {
PyObject *str; PyObject *str;
if (!PyArg_ParseTuple(args, "O", &str)) if (!PyArg_ParseTuple(args, "O", &str))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&binaryType, "O", str); return PyObject_CallFunction((PyObject *)&binaryType, "O", str);
} }

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_BINARY_H #ifndef PSYCOPG_BINARY_H
#define PSYCOPG_BINARY_H 1 #define PSYCOPG_BINARY_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <libpq-fe.h> #include <libpq-fe.h>
@ -40,7 +41,7 @@ typedef struct {
} binaryObject; } binaryObject;
/* functions exported to psycopgmodule.c */ /* functions exported to psycopgmodule.c */
extern PyObject *psyco_Binary(PyObject *module, PyObject *args); extern PyObject *psyco_Binary(PyObject *module, PyObject *args);
#define psyco_Binary_doc \ #define psyco_Binary_doc \
"Binary(buffer) -> new binary object\n\n" \ "Binary(buffer) -> new binary object\n\n" \

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <stringobject.h> #include <stringobject.h>
@ -62,11 +63,11 @@ pydatetime_str(pydatetimeObject *self)
} }
else { else {
PyDateTime_Delta *obj = (PyDateTime_Delta*)self->wrapped; PyDateTime_Delta *obj = (PyDateTime_Delta*)self->wrapped;
char buffer[8]; char buffer[8];
int i; int i;
int a = obj->microseconds; int a = obj->microseconds;
for (i=0; i < 6 ; i++) { for (i=0; i < 6 ; i++) {
buffer[5-i] = '0' + (a % 10); buffer[5-i] = '0' + (a % 10);
a /= 10; a /= 10;
@ -89,14 +90,14 @@ PyObject *
pydatetime_conform(pydatetimeObject *self, PyObject *args) pydatetime_conform(pydatetimeObject *self, PyObject *args)
{ {
PyObject *res, *proto; PyObject *res, *proto;
if (!PyArg_ParseTuple(args, "O", &proto)) return NULL; if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
if (proto == (PyObject*)&isqlquoteType) if (proto == (PyObject*)&isqlquoteType)
res = (PyObject*)self; res = (PyObject*)self;
else else
res = Py_None; res = Py_None;
Py_INCREF(res); Py_INCREF(res);
return res; return res;
} }
@ -125,15 +126,19 @@ static PyMethodDef pydatetimeObject_methods[] = {
static int static int
pydatetime_setup(pydatetimeObject *self, PyObject *obj, int type) pydatetime_setup(pydatetimeObject *self, PyObject *obj, int type)
{ {
Dprintf("pydatetime_setup: init datetime object at %p, refcnt = %d", Dprintf("pydatetime_setup: init datetime object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
self->type = type; self->type = type;
self->wrapped = obj; self->wrapped = obj;
Py_INCREF(self->wrapped); Py_INCREF(self->wrapped);
Dprintf("pydatetime_setup: good pydatetime object at %p, refcnt = %d", Dprintf("pydatetime_setup: good pydatetime object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
return 0; return 0;
} }
@ -143,10 +148,10 @@ pydatetime_dealloc(PyObject* obj)
pydatetimeObject *self = (pydatetimeObject *)obj; pydatetimeObject *self = (pydatetimeObject *)obj;
Py_XDECREF(self->wrapped); Py_XDECREF(self->wrapped);
Dprintf("mpydatetime_dealloc: deleted pydatetime object at %p, " Dprintf("mpydatetime_dealloc: deleted pydatetime object at %p, "
"refcnt = %d", obj, obj->ob_refcnt); "refcnt = " FORMAT_CODE_PY_SSIZE_T, obj, obj->ob_refcnt);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -155,7 +160,7 @@ pydatetime_init(PyObject *obj, PyObject *args, PyObject *kwds)
{ {
PyObject *dt; PyObject *dt;
int type = -1; /* raise an error if type was not passed! */ int type = -1; /* raise an error if type was not passed! */
if (!PyArg_ParseTuple(args, "O|i", &dt, &type)) if (!PyArg_ParseTuple(args, "O|i", &dt, &type))
return -1; return -1;
@ -164,7 +169,7 @@ pydatetime_init(PyObject *obj, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
pydatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds) pydatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
return type->tp_alloc(type, 0); return type->tp_alloc(type, 0);
} }
@ -195,7 +200,7 @@ PyTypeObject pydatetimeType = {
pydatetime_dealloc, /*tp_dealloc*/ pydatetime_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
(reprfunc)pydatetime_repr, /*tp_repr*/ (reprfunc)pydatetime_repr, /*tp_repr*/
@ -213,7 +218,7 @@ PyTypeObject pydatetimeType = {
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
pydatetimeType_doc, /*tp_doc*/ pydatetimeType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -230,11 +235,11 @@ PyTypeObject pydatetimeType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
pydatetime_init, /*tp_init*/ pydatetime_init, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
pydatetime_new, /*tp_new*/ pydatetime_new, /*tp_new*/
@ -253,15 +258,15 @@ PyTypeObject pydatetimeType = {
#ifdef PSYCOPG_DEFAULT_PYDATETIME #ifdef PSYCOPG_DEFAULT_PYDATETIME
PyObject * PyObject *
psyco_Date(PyObject *self, PyObject *args) psyco_Date(PyObject *self, PyObject *args)
{ {
PyObject *res = NULL; PyObject *res = NULL;
int year, month, day; int year, month, day;
PyObject* obj = NULL; PyObject* obj = NULL;
if (!PyArg_ParseTuple(args, "iii", &year, &month, &day)) if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
return NULL; return NULL;
obj = PyObject_CallFunction(pyDateTypeP, "iii", year, month, day); obj = PyObject_CallFunction(pyDateTypeP, "iii", year, month, day);
@ -275,18 +280,18 @@ psyco_Date(PyObject *self, PyObject *args)
} }
PyObject * PyObject *
psyco_Time(PyObject *self, PyObject *args) psyco_Time(PyObject *self, PyObject *args)
{ {
PyObject *res = NULL; PyObject *res = NULL;
PyObject *tzinfo = NULL; PyObject *tzinfo = NULL;
int hours, minutes=0; int hours, minutes=0;
double micro, second=0.0; double micro, second=0.0;
PyObject* obj = NULL; PyObject* obj = NULL;
if (!PyArg_ParseTuple(args, "iid|O", &hours, &minutes, &second, if (!PyArg_ParseTuple(args, "iid|O", &hours, &minutes, &second,
&tzinfo)) &tzinfo))
return NULL; return NULL;
micro = (second - floor(second)) * 1000000.0; micro = (second - floor(second)) * 1000000.0;
second = floor(second); second = floor(second);
@ -297,7 +302,7 @@ psyco_Time(PyObject *self, PyObject *args)
else else
obj = PyObject_CallFunction(pyTimeTypeP, "iiiiO", obj = PyObject_CallFunction(pyTimeTypeP, "iiiiO",
hours, minutes, (int)second, (int)round(micro), tzinfo); hours, minutes, (int)second, (int)round(micro), tzinfo);
if (obj) { if (obj) {
res = PyObject_CallFunction((PyObject *)&pydatetimeType, res = PyObject_CallFunction((PyObject *)&pydatetimeType,
"Oi", obj, PSYCO_DATETIME_TIME); "Oi", obj, PSYCO_DATETIME_TIME);
@ -308,7 +313,7 @@ psyco_Time(PyObject *self, PyObject *args)
} }
PyObject * PyObject *
psyco_Timestamp(PyObject *self, PyObject *args) psyco_Timestamp(PyObject *self, PyObject *args)
{ {
PyObject *res = NULL; PyObject *res = NULL;
PyObject *tzinfo = NULL; PyObject *tzinfo = NULL;
@ -317,10 +322,10 @@ psyco_Timestamp(PyObject *self, PyObject *args)
double micro, second=0.0; double micro, second=0.0;
PyObject* obj = NULL; PyObject* obj = NULL;
if (!PyArg_ParseTuple(args, "lii|iidO", &year, &month, &day, if (!PyArg_ParseTuple(args, "lii|iidO", &year, &month, &day,
&hour, &minute, &second, &tzinfo)) &hour, &minute, &second, &tzinfo))
return NULL; return NULL;
micro = (second - floor(second)) * 1000000.0; micro = (second - floor(second)) * 1000000.0;
second = floor(second); second = floor(second);
@ -333,13 +338,13 @@ psyco_Timestamp(PyObject *self, PyObject *args)
obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO", obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
year, month, day, hour, minute, (int)second, year, month, day, hour, minute, (int)second,
(int)round(micro), tzinfo); (int)round(micro), tzinfo);
if (obj) { if (obj) {
res = PyObject_CallFunction((PyObject *)&pydatetimeType, res = PyObject_CallFunction((PyObject *)&pydatetimeType,
"Oi", obj, PSYCO_DATETIME_TIMESTAMP); "Oi", obj, PSYCO_DATETIME_TIMESTAMP);
Py_DECREF(obj); Py_DECREF(obj);
} }
return res; return res;
} }
@ -361,8 +366,8 @@ psyco_DateFromTicks(PyObject *self, PyObject *args)
res = psyco_Date(self, args); res = psyco_Date(self, args);
Py_DECREF(args); Py_DECREF(args);
} }
} }
return res; return res;
} }
PyObject * PyObject *
@ -380,13 +385,13 @@ psyco_TimeFromTicks(PyObject *self, PyObject *args)
ticks -= (double)t; ticks -= (double)t;
if (localtime_r(&t, &tm)) { if (localtime_r(&t, &tm)) {
args = Py_BuildValue("iid", tm.tm_hour, tm.tm_min, args = Py_BuildValue("iid", tm.tm_hour, tm.tm_min,
(double)tm.tm_sec + ticks); (double)tm.tm_sec + ticks);
if (args) { if (args) {
res = psyco_Time(self, args); res = psyco_Time(self, args);
Py_DECREF(args); Py_DECREF(args);
} }
} }
return res; return res;
} }
PyObject * PyObject *
@ -399,21 +404,21 @@ psyco_TimestampFromTicks(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args,"d", &ticks)) if (!PyArg_ParseTuple(args,"d", &ticks))
return NULL; return NULL;
t = (time_t)round(ticks); t = (time_t)round(ticks);
ticks -= (double)t; ticks -= (double)t;
if (localtime_r(&t, &tm)) { if (localtime_r(&t, &tm)) {
args = Py_BuildValue("iiiiidO", args = Py_BuildValue("iiiiidO",
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_hour, tm.tm_min,
(double)tm.tm_sec + ticks, (double)tm.tm_sec + ticks,
pyPsycopgTzLOCAL); pyPsycopgTzLOCAL);
if (args) { if (args) {
res = psyco_Timestamp(self, args); res = psyco_Timestamp(self, args);
Py_DECREF(args); Py_DECREF(args);
} }
} }
return res; return res;
} }
#endif #endif
@ -425,7 +430,7 @@ psyco_DateFromPy(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O!", pyDateTypeP, &obj)) if (!PyArg_ParseTuple(args, "O!", pyDateTypeP, &obj))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj, return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
PSYCO_DATETIME_DATE); PSYCO_DATETIME_DATE);
} }
@ -437,7 +442,7 @@ psyco_TimeFromPy(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O!", pyTimeTypeP, &obj)) if (!PyArg_ParseTuple(args, "O!", pyTimeTypeP, &obj))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj, return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
PSYCO_DATETIME_TIME); PSYCO_DATETIME_TIME);
} }
@ -449,7 +454,7 @@ psyco_TimestampFromPy(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O!", pyDateTimeTypeP, &obj)) if (!PyArg_ParseTuple(args, "O!", pyDateTimeTypeP, &obj))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj, return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
PSYCO_DATETIME_TIMESTAMP); PSYCO_DATETIME_TIMESTAMP);
} }
@ -461,7 +466,7 @@ psyco_IntervalFromPy(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O!", pyDeltaTypeP, &obj)) if (!PyArg_ParseTuple(args, "O!", pyDeltaTypeP, &obj))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj, return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
PSYCO_DATETIME_INTERVAL); PSYCO_DATETIME_INTERVAL);
} }

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_DATETIME_H #ifndef PSYCOPG_DATETIME_H
#define PSYCOPG_DATETIME_H 1 #define PSYCOPG_DATETIME_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -38,14 +39,14 @@ typedef struct {
#define PSYCO_DATETIME_TIME 0 #define PSYCO_DATETIME_TIME 0
#define PSYCO_DATETIME_DATE 1 #define PSYCO_DATETIME_DATE 1
#define PSYCO_DATETIME_TIMESTAMP 2 #define PSYCO_DATETIME_TIMESTAMP 2
#define PSYCO_DATETIME_INTERVAL 3 #define PSYCO_DATETIME_INTERVAL 3
} pydatetimeObject; } pydatetimeObject;
/* functions exported to psycopgmodule.c */ /* functions exported to psycopgmodule.c */
#ifdef PSYCOPG_DEFAULT_PYDATETIME #ifdef PSYCOPG_DEFAULT_PYDATETIME
extern PyObject *psyco_Date(PyObject *module, PyObject *args); extern PyObject *psyco_Date(PyObject *module, PyObject *args);
#define psyco_Date_doc \ #define psyco_Date_doc \
"Date(year, month, day) -> new date\n\n" \ "Date(year, month, day) -> new date\n\n" \
@ -99,7 +100,7 @@ extern PyObject *psyco_TimestampFromPy(PyObject *module, PyObject *args);
extern PyObject *psyco_IntervalFromPy(PyObject *module, PyObject *args); extern PyObject *psyco_IntervalFromPy(PyObject *module, PyObject *args);
#define psyco_IntervalFromPy_doc \ #define psyco_IntervalFromPy_doc \
"IntervalFromPy(datetime.timedelta) -> new wrapper" "IntervalFromPy(datetime.timedelta) -> new wrapper"
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <stringobject.h> #include <stringobject.h>
@ -43,20 +44,20 @@ list_quote(listObject *self)
Py_ssize_t i, len; Py_ssize_t i, len;
len = PyList_GET_SIZE(self->wrapped); len = PyList_GET_SIZE(self->wrapped);
/* empty arrays are converted to NULLs (still searching for a way to /* empty arrays are converted to NULLs (still searching for a way to
insert an empty array in postgresql */ insert an empty array in postgresql */
if (len == 0) return PyString_FromString("'{}'"); if (len == 0) return PyString_FromString("'{}'");
tmp = PyTuple_New(len); tmp = PyTuple_New(len);
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
PyObject *quoted; PyObject *quoted;
PyObject *wrapped = PyList_GET_ITEM(self->wrapped, i); PyObject *wrapped = PyList_GET_ITEM(self->wrapped, i);
if (wrapped == Py_None) if (wrapped == Py_None)
quoted = PyString_FromString("NULL"); quoted = PyString_FromString("NULL");
else else
quoted = microprotocol_getquoted(wrapped, quoted = microprotocol_getquoted(wrapped,
(connectionObject*)self->connection); (connectionObject*)self->connection);
if (quoted == NULL) goto error; if (quoted == NULL) goto error;
@ -73,7 +74,7 @@ list_quote(listObject *self)
if (joined == NULL) goto error; if (joined == NULL) goto error;
res = PyString_FromFormat("ARRAY[%s]", PyString_AsString(joined)); res = PyString_FromFormat("ARRAY[%s]", PyString_AsString(joined));
error: error:
Py_XDECREF(tmp); Py_XDECREF(tmp);
Py_XDECREF(str); Py_XDECREF(str);
@ -110,7 +111,7 @@ list_prepare(listObject *self, PyObject *args)
Py_XDECREF(self->connection); Py_XDECREF(self->connection);
self->connection = (PyObject*)conn; self->connection = (PyObject*)conn;
Py_INCREF(self->connection); Py_INCREF(self->connection);
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
@ -119,14 +120,14 @@ PyObject *
list_conform(listObject *self, PyObject *args) list_conform(listObject *self, PyObject *args)
{ {
PyObject *res, *proto; PyObject *res, *proto;
if (!PyArg_ParseTuple(args, "O", &proto)) return NULL; if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
if (proto == (PyObject*)&isqlquoteType) if (proto == (PyObject*)&isqlquoteType)
res = (PyObject*)self; res = (PyObject*)self;
else else
res = Py_None; res = Py_None;
Py_INCREF(res); Py_INCREF(res);
return res; return res;
} }
@ -146,7 +147,7 @@ static PyMethodDef listObject_methods[] = {
{"getquoted", (PyCFunction)list_getquoted, METH_VARARGS, {"getquoted", (PyCFunction)list_getquoted, METH_VARARGS,
"getquoted() -> wrapped object value as SQL date/time"}, "getquoted() -> wrapped object value as SQL date/time"},
{"prepare", (PyCFunction)list_prepare, METH_VARARGS, {"prepare", (PyCFunction)list_prepare, METH_VARARGS,
"prepare(conn) -> set encoding to conn->encoding"}, "prepare(conn) -> set encoding to conn->encoding"},
{"__conform__", (PyCFunction)list_conform, METH_VARARGS, NULL}, {"__conform__", (PyCFunction)list_conform, METH_VARARGS, NULL},
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
@ -156,8 +157,10 @@ static PyMethodDef listObject_methods[] = {
static int static int
list_setup(listObject *self, PyObject *obj, char *enc) list_setup(listObject *self, PyObject *obj, char *enc)
{ {
Dprintf("list_setup: init list object at %p, refcnt = %d", Dprintf("list_setup: init list object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
if (!PyList_Check(obj)) if (!PyList_Check(obj))
return -1; return -1;
@ -168,9 +171,11 @@ list_setup(listObject *self, PyObject *obj, char *enc)
self->connection = NULL; self->connection = NULL;
self->wrapped = obj; self->wrapped = obj;
Py_INCREF(self->wrapped); Py_INCREF(self->wrapped);
Dprintf("list_setup: good list object at %p, refcnt = %d", Dprintf("list_setup: good list object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
return 0; return 0;
} }
@ -182,10 +187,10 @@ list_dealloc(PyObject* obj)
Py_XDECREF(self->wrapped); Py_XDECREF(self->wrapped);
Py_XDECREF(self->connection); Py_XDECREF(self->connection);
if (self->encoding) free(self->encoding); if (self->encoding) free(self->encoding);
Dprintf("list_dealloc: deleted list object at %p, " Dprintf("list_dealloc: deleted list object at %p, "
"refcnt = %d", obj, obj->ob_refcnt); "refcnt = " FORMAT_CODE_PY_SSIZE_T, obj, obj->ob_refcnt);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -194,7 +199,7 @@ list_init(PyObject *obj, PyObject *args, PyObject *kwds)
{ {
PyObject *l; PyObject *l;
char *enc = "latin-1"; /* default encoding as in Python */ char *enc = "latin-1"; /* default encoding as in Python */
if (!PyArg_ParseTuple(args, "O|s", &l, &enc)) if (!PyArg_ParseTuple(args, "O|s", &l, &enc))
return -1; return -1;
@ -203,7 +208,7 @@ list_init(PyObject *obj, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
list_new(PyTypeObject *type, PyObject *args, PyObject *kwds) list_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
return type->tp_alloc(type, 0); return type->tp_alloc(type, 0);
} }
@ -233,7 +238,7 @@ PyTypeObject listType = {
list_dealloc, /*tp_dealloc*/ list_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
(reprfunc)list_repr, /*tp_repr*/ (reprfunc)list_repr, /*tp_repr*/
@ -251,7 +256,7 @@ PyTypeObject listType = {
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
listType_doc, /*tp_doc*/ listType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -268,11 +273,11 @@ PyTypeObject listType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
list_init, /*tp_init*/ list_init, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
list_new, /*tp_new*/ list_new, /*tp_new*/
@ -293,9 +298,9 @@ psyco_List(PyObject *module, PyObject *args)
{ {
PyObject *str; PyObject *str;
char *enc = "latin-1"; /* default encoding as in Python */ char *enc = "latin-1"; /* default encoding as in Python */
if (!PyArg_ParseTuple(args, "O|s", &str, &enc)) if (!PyArg_ParseTuple(args, "O|s", &str, &enc))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&listType, "Os", str, enc); return PyObject_CallFunction((PyObject *)&listType, "Os", str, enc);
} }

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_LIST_H #ifndef PSYCOPG_LIST_H
#define PSYCOPG_LIST_H 1 #define PSYCOPG_LIST_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <stringobject.h> #include <stringobject.h>
@ -68,23 +69,23 @@ mxdatetime_str(mxdatetimeObject *self)
/* given the limitation of the mx.DateTime module that uses the same /* given the limitation of the mx.DateTime module that uses the same
type for both time and delta values we need to do some black magic type for both time and delta values we need to do some black magic
and make sure we're not using an adapt()ed interval as a simple and make sure we're not using an adapt()ed interval as a simple
time */ time */
if (PyString_Size(str) > 8 && PyString_AsString(str)[8] == ':') { if (PyString_Size(str) > 8 && PyString_AsString(str)[8] == ':') {
mxDateTimeDeltaObject *obj = (mxDateTimeDeltaObject*)self->wrapped; mxDateTimeDeltaObject *obj = (mxDateTimeDeltaObject*)self->wrapped;
char buffer[8]; char buffer[8];
int i, j, x; int i, j, x;
double ss = obj->hour*3600.0 + obj->minute*60.0 + obj->second; double ss = obj->hour*3600.0 + obj->minute*60.0 + obj->second;
int us = (int)((ss - floor(ss))*1000000); int us = (int)((ss - floor(ss))*1000000);
for (i=1000000, j=0; i > 0 ; i /= 10) { for (i=1000000, j=0; i > 0 ; i /= 10) {
x = us/i; x = us/i;
us -= x*i; us -= x*i;
buffer[j++] = '0'+x; buffer[j++] = '0'+x;
} }
buffer[j] = '\0'; buffer[j] = '\0';
res = PyString_FromFormat("'%ld days %d.%s seconds'", res = PyString_FromFormat("'%ld days %d.%s seconds'",
obj->day, (int)round(ss), buffer); obj->day, (int)round(ss), buffer);
} }
@ -94,7 +95,7 @@ mxdatetime_str(mxdatetimeObject *self)
if (str != NULL && res == NULL) { if (str != NULL && res == NULL) {
res = PyString_FromFormat("'%s'", PyString_AsString(str)); res = PyString_FromFormat("'%s'", PyString_AsString(str));
} }
Py_XDECREF(str); Py_XDECREF(str);
return res; return res;
} }
@ -110,14 +111,14 @@ PyObject *
mxdatetime_conform(mxdatetimeObject *self, PyObject *args) mxdatetime_conform(mxdatetimeObject *self, PyObject *args)
{ {
PyObject *res, *proto; PyObject *res, *proto;
if (!PyArg_ParseTuple(args, "O", &proto)) return NULL; if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
if (proto == (PyObject*)&isqlquoteType) if (proto == (PyObject*)&isqlquoteType)
res = (PyObject*)self; res = (PyObject*)self;
else else
res = Py_None; res = Py_None;
Py_INCREF(res); Py_INCREF(res);
return res; return res;
} }
@ -146,15 +147,19 @@ static PyMethodDef mxdatetimeObject_methods[] = {
static int static int
mxdatetime_setup(mxdatetimeObject *self, PyObject *obj, int type) mxdatetime_setup(mxdatetimeObject *self, PyObject *obj, int type)
{ {
Dprintf("mxdatetime_setup: init mxdatetime object at %p, refcnt = %d", Dprintf("mxdatetime_setup: init mxdatetime object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
self->type = type; self->type = type;
self->wrapped = obj; self->wrapped = obj;
Py_INCREF(self->wrapped); Py_INCREF(self->wrapped);
Dprintf("mxdatetime_setup: good mxdatetime object at %p, refcnt = %d", Dprintf("mxdatetime_setup: good mxdatetime object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
return 0; return 0;
} }
@ -164,10 +169,12 @@ mxdatetime_dealloc(PyObject* obj)
mxdatetimeObject *self = (mxdatetimeObject *)obj; mxdatetimeObject *self = (mxdatetimeObject *)obj;
Py_XDECREF(self->wrapped); Py_XDECREF(self->wrapped);
Dprintf("mxdatetime_dealloc: deleted mxdatetime object at %p, refcnt = %d", Dprintf("mxdatetime_dealloc: deleted mxdatetime object at %p, refcnt = "
obj, obj->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
obj, obj->ob_refcnt
);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -176,7 +183,7 @@ mxdatetime_init(PyObject *obj, PyObject *args, PyObject *kwds)
{ {
PyObject *mx; PyObject *mx;
int type = -1; /* raise an error if type was not passed! */ int type = -1; /* raise an error if type was not passed! */
if (!PyArg_ParseTuple(args, "O|i", &mx, &type)) if (!PyArg_ParseTuple(args, "O|i", &mx, &type))
return -1; return -1;
@ -185,7 +192,7 @@ mxdatetime_init(PyObject *obj, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
mxdatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds) mxdatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
return type->tp_alloc(type, 0); return type->tp_alloc(type, 0);
} }
@ -216,7 +223,7 @@ PyTypeObject mxdatetimeType = {
mxdatetime_dealloc, /*tp_dealloc*/ mxdatetime_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
(reprfunc)mxdatetime_repr, /*tp_repr*/ (reprfunc)mxdatetime_repr, /*tp_repr*/
@ -234,7 +241,7 @@ PyTypeObject mxdatetimeType = {
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
mxdatetimeType_doc, /*tp_doc*/ mxdatetimeType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -251,11 +258,11 @@ PyTypeObject mxdatetimeType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
mxdatetime_init, /*tp_init*/ mxdatetime_init, /*tp_init*/
0, /*tp_alloc*/ 0, /*tp_alloc*/
mxdatetime_new, /*tp_new*/ mxdatetime_new, /*tp_new*/
@ -274,15 +281,15 @@ PyTypeObject mxdatetimeType = {
#ifdef PSYCOPG_DEFAULT_MXDATETIME #ifdef PSYCOPG_DEFAULT_MXDATETIME
PyObject * PyObject *
psyco_Date(PyObject *self, PyObject *args) psyco_Date(PyObject *self, PyObject *args)
{ {
PyObject *res, *mx; PyObject *res, *mx;
int year, month, day; int year, month, day;
if (!PyArg_ParseTuple(args, "iii", &year, &month, &day)) if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
return NULL; return NULL;
mx = mxDateTimeP->DateTime_FromDateAndTime(year, month, day, 0, 0, 0.0); mx = mxDateTimeP->DateTime_FromDateAndTime(year, month, day, 0, 0, 0.0);
if (mx == NULL) return NULL; if (mx == NULL) return NULL;
res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
@ -292,35 +299,35 @@ psyco_Date(PyObject *self, PyObject *args)
} }
PyObject * PyObject *
psyco_Time(PyObject *self, PyObject *args) psyco_Time(PyObject *self, PyObject *args)
{ {
PyObject *res, *mx; PyObject *res, *mx;
int hours, minutes=0; int hours, minutes=0;
double seconds=0.0; double seconds=0.0;
if (!PyArg_ParseTuple(args, "iid", &hours, &minutes, &seconds)) if (!PyArg_ParseTuple(args, "iid", &hours, &minutes, &seconds))
return NULL; return NULL;
mx = mxDateTimeP->DateTimeDelta_FromTime(hours, minutes, seconds); mx = mxDateTimeP->DateTimeDelta_FromTime(hours, minutes, seconds);
if (mx == NULL) return NULL; if (mx == NULL) return NULL;
res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
PSYCO_MXDATETIME_TIME); PSYCO_MXDATETIME_TIME);
Py_DECREF(mx); Py_DECREF(mx);
return res; return res;
} }
PyObject * PyObject *
psyco_Timestamp(PyObject *self, PyObject *args) psyco_Timestamp(PyObject *self, PyObject *args)
{ {
PyObject *res, *mx; PyObject *res, *mx;
int year, month, day; int year, month, day;
int hour=0, minute=0; /* default to midnight */ int hour=0, minute=0; /* default to midnight */
double second=0.0; double second=0.0;
if (!PyArg_ParseTuple(args, "lii|iid", &year, &month, &day, if (!PyArg_ParseTuple(args, "lii|iid", &year, &month, &day,
&hour, &minute, &second)) &hour, &minute, &second))
return NULL; return NULL;
mx = mxDateTimeP->DateTime_FromDateAndTime(year, month, day, mx = mxDateTimeP->DateTime_FromDateAndTime(year, month, day,
hour, minute, second); hour, minute, second);
@ -329,7 +336,7 @@ psyco_Timestamp(PyObject *self, PyObject *args)
res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
PSYCO_MXDATETIME_TIMESTAMP); PSYCO_MXDATETIME_TIMESTAMP);
Py_DECREF(mx); Py_DECREF(mx);
return res; return res;
} }
PyObject * PyObject *
@ -340,14 +347,14 @@ psyco_DateFromTicks(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args,"d", &ticks)) if (!PyArg_ParseTuple(args,"d", &ticks))
return NULL; return NULL;
if (!(mx = mxDateTimeP->DateTime_FromTicks(ticks))) if (!(mx = mxDateTimeP->DateTime_FromTicks(ticks)))
return NULL; return NULL;
res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
PSYCO_MXDATETIME_DATE); PSYCO_MXDATETIME_DATE);
Py_DECREF(mx); Py_DECREF(mx);
return res; return res;
} }
PyObject * PyObject *
@ -358,7 +365,7 @@ psyco_TimeFromTicks(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args,"d", &ticks)) if (!PyArg_ParseTuple(args,"d", &ticks))
return NULL; return NULL;
if (!(dt = mxDateTimeP->DateTime_FromTicks(ticks))) if (!(dt = mxDateTimeP->DateTime_FromTicks(ticks)))
return NULL; return NULL;
@ -373,7 +380,7 @@ psyco_TimeFromTicks(PyObject *self, PyObject *args)
res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
PSYCO_MXDATETIME_TIME); PSYCO_MXDATETIME_TIME);
Py_DECREF(mx); Py_DECREF(mx);
return res; return res;
} }
PyObject * PyObject *
@ -384,14 +391,14 @@ psyco_TimestampFromTicks(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "d", &ticks)) if (!PyArg_ParseTuple(args, "d", &ticks))
return NULL; return NULL;
if (!(mx = mxDateTimeP->DateTime_FromTicks(ticks))) if (!(mx = mxDateTimeP->DateTime_FromTicks(ticks)))
return NULL; return NULL;
res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
PSYCO_MXDATETIME_TIMESTAMP); PSYCO_MXDATETIME_TIMESTAMP);
Py_DECREF(mx); Py_DECREF(mx);
return res; return res;
} }
#endif #endif
@ -403,7 +410,7 @@ psyco_DateFromMx(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx)) if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
PSYCO_MXDATETIME_DATE); PSYCO_MXDATETIME_DATE);
} }
@ -415,7 +422,7 @@ psyco_TimeFromMx(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTimeDelta_Type, &mx)) if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTimeDelta_Type, &mx))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
PSYCO_MXDATETIME_TIME); PSYCO_MXDATETIME_TIME);
} }
@ -427,7 +434,7 @@ psyco_TimestampFromMx(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx)) if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
PSYCO_MXDATETIME_TIMESTAMP); PSYCO_MXDATETIME_TIMESTAMP);
} }
@ -439,7 +446,7 @@ psyco_IntervalFromMx(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx)) if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx, return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
PSYCO_MXDATETIME_INTERVAL); PSYCO_MXDATETIME_INTERVAL);
} }

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_MXDATETIME_H #ifndef PSYCOPG_MXDATETIME_H
#define PSYCOPG_MXDATETIME_H 1 #define PSYCOPG_MXDATETIME_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -38,13 +39,13 @@ typedef struct {
#define PSYCO_MXDATETIME_TIME 0 #define PSYCO_MXDATETIME_TIME 0
#define PSYCO_MXDATETIME_DATE 1 #define PSYCO_MXDATETIME_DATE 1
#define PSYCO_MXDATETIME_TIMESTAMP 2 #define PSYCO_MXDATETIME_TIMESTAMP 2
#define PSYCO_MXDATETIME_INTERVAL 3 #define PSYCO_MXDATETIME_INTERVAL 3
} mxdatetimeObject; } mxdatetimeObject;
/* functions exported to psycopgmodule.c */ /* functions exported to psycopgmodule.c */
#ifdef PSYCOPG_DEFAULT_MXDATETIME #ifdef PSYCOPG_DEFAULT_MXDATETIME
extern PyObject *psyco_Date(PyObject *module, PyObject *args); extern PyObject *psyco_Date(PyObject *module, PyObject *args);
#define psyco_Date_doc \ #define psyco_Date_doc \
"Date(year, month, day) -> new date" "Date(year, month, day) -> new date"
@ -56,7 +57,7 @@ extern PyObject *psyco_Time(PyObject *module, PyObject *args);
extern PyObject *psyco_Timestamp(PyObject *module, PyObject *args); extern PyObject *psyco_Timestamp(PyObject *module, PyObject *args);
#define psyco_Timestamp_doc \ #define psyco_Timestamp_doc \
"Time(year, month, day, hour, minutes, seconds) -> new timestamp" "Time(year, month, day, hour, minutes, seconds) -> new timestamp"
extern PyObject *psyco_DateFromTicks(PyObject *module, PyObject *args); extern PyObject *psyco_DateFromTicks(PyObject *module, PyObject *args);
#define psyco_DateFromTicks_doc \ #define psyco_DateFromTicks_doc \
"DateFromTicks(ticks) -> new date" "DateFromTicks(ticks) -> new date"
@ -86,7 +87,7 @@ extern PyObject *psyco_TimestampFromMx(PyObject *module, PyObject *args);
extern PyObject *psyco_IntervalFromMx(PyObject *module, PyObject *args); extern PyObject *psyco_IntervalFromMx(PyObject *module, PyObject *args);
#define psyco_IntervalFromMx_doc \ #define psyco_IntervalFromMx_doc \
"IntervalFromMx(mx) -> new interval" "IntervalFromMx(mx) -> new interval"
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <stringobject.h> #include <stringobject.h>
@ -65,14 +66,14 @@ PyObject *
pboolean_conform(pbooleanObject *self, PyObject *args) pboolean_conform(pbooleanObject *self, PyObject *args)
{ {
PyObject *res, *proto; PyObject *res, *proto;
if (!PyArg_ParseTuple(args, "O", &proto)) return NULL; if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
if (proto == (PyObject*)&isqlquoteType) if (proto == (PyObject*)&isqlquoteType)
res = (PyObject*)self; res = (PyObject*)self;
else else
res = Py_None; res = Py_None;
Py_INCREF(res); Py_INCREF(res);
return res; return res;
} }
@ -100,14 +101,18 @@ static PyMethodDef pbooleanObject_methods[] = {
static int static int
pboolean_setup(pbooleanObject *self, PyObject *obj) pboolean_setup(pbooleanObject *self, PyObject *obj)
{ {
Dprintf("pboolean_setup: init pboolean object at %p, refcnt = %d", Dprintf("pboolean_setup: init pboolean object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
self->wrapped = obj; self->wrapped = obj;
Py_INCREF(self->wrapped); Py_INCREF(self->wrapped);
Dprintf("pboolean_setup: good pboolean object at %p, refcnt = %d", Dprintf("pboolean_setup: good pboolean object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
return 0; return 0;
} }
@ -117,10 +122,12 @@ pboolean_dealloc(PyObject* obj)
pbooleanObject *self = (pbooleanObject *)obj; pbooleanObject *self = (pbooleanObject *)obj;
Py_XDECREF(self->wrapped); Py_XDECREF(self->wrapped);
Dprintf("pboolean_dealloc: deleted pboolean object at %p, refcnt = %d", Dprintf("pboolean_dealloc: deleted pboolean object at %p, refcnt = "
obj, obj->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
obj, obj->ob_refcnt
);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -128,7 +135,7 @@ static int
pboolean_init(PyObject *obj, PyObject *args, PyObject *kwds) pboolean_init(PyObject *obj, PyObject *args, PyObject *kwds)
{ {
PyObject *o; PyObject *o;
if (!PyArg_ParseTuple(args, "O", &o)) if (!PyArg_ParseTuple(args, "O", &o))
return -1; return -1;
@ -137,7 +144,7 @@ pboolean_init(PyObject *obj, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
pboolean_new(PyTypeObject *type, PyObject *args, PyObject *kwds) pboolean_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
return type->tp_alloc(type, 0); return type->tp_alloc(type, 0);
} }
@ -170,7 +177,7 @@ PyTypeObject pbooleanType = {
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
@ -182,14 +189,14 @@ PyTypeObject pbooleanType = {
0, /*tp_call*/ 0, /*tp_call*/
(reprfunc)pboolean_str, /*tp_str*/ (reprfunc)pboolean_str, /*tp_str*/
0, /*tp_getattro*/ 0, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
pbooleanType_doc, /*tp_doc*/ pbooleanType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -206,11 +213,11 @@ PyTypeObject pbooleanType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
pboolean_init, /*tp_init*/ pboolean_init, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
pboolean_new, /*tp_new*/ pboolean_new, /*tp_new*/
@ -230,9 +237,9 @@ PyObject *
psyco_Boolean(PyObject *module, PyObject *args) psyco_Boolean(PyObject *module, PyObject *args)
{ {
PyObject *obj; PyObject *obj;
if (!PyArg_ParseTuple(args, "O", &obj)) if (!PyArg_ParseTuple(args, "O", &obj))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&pbooleanType, "O", obj); return PyObject_CallFunction((PyObject *)&pbooleanType, "O", obj);
} }

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_PBOOLEAN_H #ifndef PSYCOPG_PBOOLEAN_H
#define PSYCOPG_PBOOLEAN_H 1 #define PSYCOPG_PBOOLEAN_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -39,7 +40,7 @@ typedef struct {
} pbooleanObject; } pbooleanObject;
/* functions exported to psycopgmodule.c */ /* functions exported to psycopgmodule.c */
extern PyObject *psyco_Boolean(PyObject *module, PyObject *args); extern PyObject *psyco_Boolean(PyObject *module, PyObject *args);
#define psyco_Boolean_doc \ #define psyco_Boolean_doc \
"Boolean(obj) -> new boolean value" "Boolean(obj) -> new boolean value"

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <stringobject.h> #include <stringobject.h>
@ -100,7 +101,7 @@ qstring_quote(qstringObject *self)
/* TODO: we need a real translation table from postgres encoding names to /* TODO: we need a real translation table from postgres encoding names to
python ones here */ python ones here */
Dprintf("qstring_quote: encoding to %s", self->encoding); Dprintf("qstring_quote: encoding to %s", self->encoding);
if (PyUnicode_Check(self->wrapped) && self->encoding) { if (PyUnicode_Check(self->wrapped) && self->encoding) {
@ -129,8 +130,8 @@ qstring_quote(qstringObject *self)
/* INCREF to make it ref-wise identical to unicode one */ /* INCREF to make it ref-wise identical to unicode one */
Py_INCREF(str); Py_INCREF(str);
} }
/* if the wrapped object is not a string, this is an error */ /* if the wrapped object is not a string, this is an error */
else { else {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"can't quote non-string object (or missing encoding)"); "can't quote non-string object (or missing encoding)");
@ -139,7 +140,7 @@ qstring_quote(qstringObject *self)
/* encode the string into buffer */ /* encode the string into buffer */
PyString_AsStringAndSize(str, &s, &len); PyString_AsStringAndSize(str, &s, &len);
buffer = (char *)PyMem_Malloc((len*2+3) * sizeof(char)); buffer = (char *)PyMem_Malloc((len*2+3) * sizeof(char));
if (buffer == NULL) { if (buffer == NULL) {
Py_DECREF(str); Py_DECREF(str);
@ -152,11 +153,11 @@ qstring_quote(qstringObject *self)
self->conn ? ((connectionObject*)self->conn)->pgconn : NULL); self->conn ? ((connectionObject*)self->conn)->pgconn : NULL);
buffer[0] = '\'' ; buffer[len+1] = '\''; buffer[0] = '\'' ; buffer[len+1] = '\'';
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
self->buffer = PyString_FromStringAndSize(buffer, len+2); self->buffer = PyString_FromStringAndSize(buffer, len+2);
PyMem_Free(buffer); PyMem_Free(buffer);
Py_DECREF(str); Py_DECREF(str);
return self->buffer; return self->buffer;
} }
@ -204,19 +205,19 @@ qstring_prepare(qstringObject *self, PyObject *args)
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
PyObject * PyObject *
qstring_conform(qstringObject *self, PyObject *args) qstring_conform(qstringObject *self, PyObject *args)
{ {
PyObject *res, *proto; PyObject *res, *proto;
if (!PyArg_ParseTuple(args, "O", &proto)) return NULL; if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
if (proto == (PyObject*)&isqlquoteType) if (proto == (PyObject*)&isqlquoteType)
res = (PyObject*)self; res = (PyObject*)self;
else else
res = Py_None; res = Py_None;
Py_INCREF(res); Py_INCREF(res);
return res; return res;
} }
@ -248,20 +249,24 @@ static PyMethodDef qstringObject_methods[] = {
static int static int
qstring_setup(qstringObject *self, PyObject *str, char *enc) qstring_setup(qstringObject *self, PyObject *str, char *enc)
{ {
Dprintf("qstring_setup: init qstring object at %p, refcnt = %d", Dprintf("qstring_setup: init qstring object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
self->buffer = NULL; self->buffer = NULL;
self->conn = NULL; self->conn = NULL;
/* FIXME: remove this orrible strdup */ /* FIXME: remove this orrible strdup */
if (enc) self->encoding = strdup(enc); if (enc) self->encoding = strdup(enc);
self->wrapped = str; self->wrapped = str;
Py_INCREF(self->wrapped); Py_INCREF(self->wrapped);
Dprintf("qstring_setup: good qstring object at %p, refcnt = %d", Dprintf("qstring_setup: good qstring object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
return 0; return 0;
} }
@ -275,10 +280,12 @@ qstring_dealloc(PyObject* obj)
Py_XDECREF(self->conn); Py_XDECREF(self->conn);
if (self->encoding) free(self->encoding); if (self->encoding) free(self->encoding);
Dprintf("qstring_dealloc: deleted qstring object at %p, refcnt = %d", Dprintf("qstring_dealloc: deleted qstring object at %p, refcnt = "
obj, obj->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
obj, obj->ob_refcnt
);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -287,7 +294,7 @@ qstring_init(PyObject *obj, PyObject *args, PyObject *kwds)
{ {
PyObject *str; PyObject *str;
char *enc = "latin-1"; /* default encoding as in Python */ char *enc = "latin-1"; /* default encoding as in Python */
if (!PyArg_ParseTuple(args, "O|s", &str, &enc)) if (!PyArg_ParseTuple(args, "O|s", &str, &enc))
return -1; return -1;
@ -296,7 +303,7 @@ qstring_init(PyObject *obj, PyObject *args, PyObject *kwds)
static PyObject * static PyObject *
qstring_new(PyTypeObject *type, PyObject *args, PyObject *kwds) qstring_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
return type->tp_alloc(type, 0); return type->tp_alloc(type, 0);
} }
@ -309,7 +316,7 @@ qstring_del(PyObject* self)
static PyObject * static PyObject *
qstring_repr(qstringObject *self) qstring_repr(qstringObject *self)
{ {
return PyString_FromFormat("<psycopg2._psycopg.QuotedString object at %p>", return PyString_FromFormat("<psycopg2._psycopg.QuotedString object at %p>",
self); self);
} }
@ -327,7 +334,7 @@ PyTypeObject qstringType = {
qstring_dealloc, /*tp_dealloc*/ qstring_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
(reprfunc)qstring_repr, /*tp_repr*/ (reprfunc)qstring_repr, /*tp_repr*/
@ -345,7 +352,7 @@ PyTypeObject qstringType = {
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
qstringType_doc, /*tp_doc*/ qstringType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -362,11 +369,11 @@ PyTypeObject qstringType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
qstring_init, /*tp_init*/ qstring_init, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
qstring_new, /*tp_new*/ qstring_new, /*tp_new*/
@ -387,9 +394,9 @@ psyco_QuotedString(PyObject *module, PyObject *args)
{ {
PyObject *str; PyObject *str;
char *enc = "latin-1"; /* default encoding as in Python */ char *enc = "latin-1"; /* default encoding as in Python */
if (!PyArg_ParseTuple(args, "O|s", &str, &enc)) if (!PyArg_ParseTuple(args, "O|s", &str, &enc))
return NULL; return NULL;
return PyObject_CallFunction((PyObject *)&qstringType, "Os", str, enc); return PyObject_CallFunction((PyObject *)&qstringType, "Os", str, enc);
} }

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_QSTRING_H #ifndef PSYCOPG_QSTRING_H
#define PSYCOPG_QSTRING_H 1 #define PSYCOPG_QSTRING_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -39,9 +40,9 @@ typedef struct {
PyObject *conn; PyObject *conn;
} qstringObject; } qstringObject;
/* functions exported to psycopgmodule.c */ /* functions exported to psycopgmodule.c */
extern PyObject *psyco_QuotedString(PyObject *module, PyObject *args); extern PyObject *psyco_QuotedString(PyObject *module, PyObject *args);
#define psyco_QuotedString_doc \ #define psyco_QuotedString_doc \
"QuotedString(str, enc) -> new quoted string" "QuotedString(str, enc) -> new quoted string"

View File

@ -28,7 +28,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#define Dprintf(fmt, args...) \ #define Dprintf(fmt, args...) \
fprintf(stderr, "[%d] " fmt "\n", getpid() , ## args) fprintf(stderr, "[%d] " fmt "\n", (int) getpid() , ## args)
#else #else
#define Dprintf(fmt, args...) #define Dprintf(fmt, args...)
#endif #endif

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_CONNECTION_H #ifndef PSYCOPG_CONNECTION_H
#define PSYCOPG_CONNECTION_H 1 #define PSYCOPG_CONNECTION_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <libpq-fe.h> #include <libpq-fe.h>
@ -34,7 +35,7 @@ extern "C" {
#define CONN_STATUS_BEGIN 2 #define CONN_STATUS_BEGIN 2
#define CONN_STATUS_SYNC 3 #define CONN_STATUS_SYNC 3
#define CONN_STATUS_ASYNC 4 #define CONN_STATUS_ASYNC 4
extern PyTypeObject connectionType; extern PyTypeObject connectionType;
typedef struct { typedef struct {
@ -45,17 +46,17 @@ typedef struct {
char *dsn; /* data source name */ char *dsn; /* data source name */
char *critical; /* critical error on this connection */ char *critical; /* critical error on this connection */
char *encoding; /* current backend encoding */ char *encoding; /* current backend encoding */
long int closed; /* 2 means connection has been closed */ long int closed; /* 2 means connection has been closed */
long int isolation_level; /* isolation level for this connection */ long int isolation_level; /* isolation level for this connection */
long int mark; /* number of commits/rollbacks done so far */ long int mark; /* number of commits/rollbacks done so far */
int status; /* status of the connection */ int status; /* status of the connection */
int protocol; /* protocol version */ int protocol; /* protocol version */
PGconn *pgconn; /* the postgresql connection */ PGconn *pgconn; /* the postgresql connection */
PyObject *async_cursor; PyObject *async_cursor;
/* notice processing */ /* notice processing */
PyObject *notice_list; PyObject *notice_list;
PyObject *notice_filter; PyObject *notice_filter;
@ -80,20 +81,20 @@ typedef struct {
PyObject *binary_types; /* a set of typecasters for binary types */ PyObject *binary_types; /* a set of typecasters for binary types */
} connectionObject; } connectionObject;
/* C-callable functions in connection_int.c and connection_ext.c */ /* C-callable functions in connection_int.c and connection_ext.c */
extern int conn_connect(connectionObject *self); extern int conn_connect(connectionObject *self);
extern void conn_close(connectionObject *self); extern void conn_close(connectionObject *self);
extern int conn_commit(connectionObject *self); extern int conn_commit(connectionObject *self);
extern int conn_rollback(connectionObject *self); extern int conn_rollback(connectionObject *self);
extern int conn_switch_isolation_level(connectionObject *self, int level); extern int conn_switch_isolation_level(connectionObject *self, int level);
extern int conn_set_client_encoding(connectionObject *self, char *enc); extern int conn_set_client_encoding(connectionObject *self, char *enc);
/* exception-raising macros */ /* exception-raising macros */
#define EXC_IF_CONN_CLOSED(self) if ((self)->closed > 0) { \ #define EXC_IF_CONN_CLOSED(self) if ((self)->closed > 0) { \
PyErr_SetString(InterfaceError, "connection already closed"); \ PyErr_SetString(InterfaceError, "connection already closed"); \
return NULL; } return NULL; }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <string.h> #include <string.h>
@ -55,22 +56,22 @@ conn_connect(connectionObject *self)
PGresult *pgres; PGresult *pgres;
char *data, *tmp; char *data, *tmp;
int i; int i;
/* we need the initial date style to be ISO, for typecasters; if the user /* we need the initial date style to be ISO, for typecasters; if the user
later change it, she must know what she's doing... */ later change it, she must know what she's doing... */
const char *datestyle = "SET DATESTYLE TO 'ISO'"; const char *datestyle = "SET DATESTYLE TO 'ISO'";
const char *encoding = "SHOW client_encoding"; const char *encoding = "SHOW client_encoding";
const char *isolevel = "SHOW default_transaction_isolation"; const char *isolevel = "SHOW default_transaction_isolation";
const char *lvl1a = "read uncommitted"; const char *lvl1a = "read uncommitted";
const char *lvl1b = "read committed"; const char *lvl1b = "read committed";
const char *lvl2a = "repeatable read"; const char *lvl2a = "repeatable read";
const char *lvl2b = "serializable"; const char *lvl2b = "serializable";
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
pgconn = PQconnectdb(self->dsn); pgconn = PQconnectdb(self->dsn);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
Dprintf("conn_connect: new postgresql connection at %p", pgconn); Dprintf("conn_connect: new postgresql connection at %p", pgconn);
if (pgconn == NULL) if (pgconn == NULL)
@ -118,12 +119,12 @@ conn_connect(connectionObject *self)
PQfinish(pgconn); PQfinish(pgconn);
IFCLEARPGRES(pgres); IFCLEARPGRES(pgres);
return -1; return -1;
} }
for (i=0 ; i < strlen(tmp) ; i++) for (i=0 ; i < strlen(tmp) ; i++)
self->encoding[i] = toupper(tmp[i]); self->encoding[i] = toupper(tmp[i]);
self->encoding[i] = '\0'; self->encoding[i] = '\0';
CLEARPGRES(pgres); CLEARPGRES(pgres);
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
pgres = PQexec(pgconn, isolevel); pgres = PQexec(pgconn, isolevel);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
@ -159,7 +160,7 @@ conn_connect(connectionObject *self)
self->protocol = 2; self->protocol = 2;
#endif #endif
Dprintf("conn_connect: using protocol %d", self->protocol); Dprintf("conn_connect: using protocol %d", self->protocol);
self->pgconn = pgconn; self->pgconn = pgconn;
return 0; return 0;
} }
@ -178,7 +179,7 @@ conn_close(connectionObject *self)
self->closed = 1; self->closed = 1;
/* execute a forced rollback on the connection (but don't check the /* execute a forced rollback on the connection (but don't check the
result, we're going to close the pq connection anyway */ result, we're going to close the pq connection anyway */
if (self->pgconn) { if (self->pgconn) {
pq_abort(self); pq_abort(self);
PQfinish(self->pgconn); PQfinish(self->pgconn);
@ -203,7 +204,7 @@ conn_commit(connectionObject *self)
res = pq_commit(self); res = pq_commit(self);
self->mark++; self->mark++;
pthread_mutex_unlock(&self->lock); pthread_mutex_unlock(&self->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
@ -222,7 +223,7 @@ conn_rollback(connectionObject *self)
res = pq_abort(self); res = pq_abort(self);
self->mark++; self->mark++;
pthread_mutex_unlock(&self->lock); pthread_mutex_unlock(&self->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
@ -241,7 +242,7 @@ conn_switch_isolation_level(connectionObject *self, int level)
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&self->lock); pthread_mutex_lock(&self->lock);
/* if the current isolation level is > 0 we need to abort the current /* if the current isolation level is > 0 we need to abort the current
transaction before changing; that all folks! */ transaction before changing; that all folks! */
if (self->isolation_level != level && self->isolation_level > 0) { if (self->isolation_level != level && self->isolation_level > 0) {
@ -249,13 +250,13 @@ conn_switch_isolation_level(connectionObject *self, int level)
} }
self->isolation_level = level; self->isolation_level = level;
self->mark++; self->mark++;
Dprintf("conn_switch_isolation_level: switched to level %d", level); Dprintf("conn_switch_isolation_level: switched to level %d", level);
pthread_mutex_unlock(&self->lock); pthread_mutex_unlock(&self->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
return res; return res;
} }
/* conn_set_client_encoding - switch client encoding on connection */ /* conn_set_client_encoding - switch client encoding on connection */
@ -266,16 +267,16 @@ conn_set_client_encoding(connectionObject *self, char *enc)
PGresult *pgres; PGresult *pgres;
char query[48]; char query[48];
int res = 0; int res = 0;
/* If the current encoding is equal to the requested one we don't /* If the current encoding is equal to the requested one we don't
issue any query to the backend */ issue any query to the backend */
if (strcmp(self->encoding, enc) == 0) return 0; if (strcmp(self->encoding, enc) == 0) return 0;
/* TODO: check for async query here and raise error if necessary */ /* TODO: check for async query here and raise error if necessary */
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&self->lock); pthread_mutex_lock(&self->lock);
/* set encoding, no encoding string is longer than 24 bytes */ /* set encoding, no encoding string is longer than 24 bytes */
PyOS_snprintf(query, 47, "SET client_encoding = '%s'", enc); PyOS_snprintf(query, 47, "SET client_encoding = '%s'", enc);
@ -297,14 +298,14 @@ conn_set_client_encoding(connectionObject *self, char *enc)
IFCLEARPGRES(pgres); IFCLEARPGRES(pgres);
} }
Dprintf("conn_set_client_encoding: set encoding to %s", self->encoding); Dprintf("conn_set_client_encoding: set encoding to %s", self->encoding);
pthread_mutex_unlock(&self->lock); pthread_mutex_unlock(&self->lock);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
if (res == -1) if (res == -1)
PyErr_Format(OperationalError, "can't set encoding to %s", enc); PyErr_Format(OperationalError, "can't set encoding to %s", enc);
return res; return res;
} }

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <stringobject.h> #include <stringobject.h>
@ -52,7 +53,7 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *keywds)
PyObject *obj, *factory = NULL; PyObject *obj, *factory = NULL;
static char *kwlist[] = {"name", "cursor_factory", NULL}; static char *kwlist[] = {"name", "cursor_factory", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sO", kwlist, if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sO", kwlist,
&name, &factory)) { &name, &factory)) {
return NULL; return NULL;
@ -62,10 +63,10 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *keywds)
Dprintf("psyco_conn_cursor: new cursor for connection at %p", self); Dprintf("psyco_conn_cursor: new cursor for connection at %p", self);
Dprintf("psyco_conn_cursor: parameters: name = %s", name); Dprintf("psyco_conn_cursor: parameters: name = %s", name);
if (factory == NULL) factory = (PyObject *)&cursorType; if (factory == NULL) factory = (PyObject *)&cursorType;
if (name) if (name)
obj = PyObject_CallFunction(factory, "Os", self, name); obj = PyObject_CallFunction(factory, "Os", self, name);
else else
obj = PyObject_CallFunction(factory, "O", self); obj = PyObject_CallFunction(factory, "O", self);
@ -76,9 +77,11 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *keywds)
Py_DECREF(obj); Py_DECREF(obj);
return NULL; return NULL;
} }
Dprintf("psyco_conn_cursor: new cursor at %p: refcnt = %d", Dprintf("psyco_conn_cursor: new cursor at %p: refcnt = "
obj, obj->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
obj, obj->ob_refcnt
);
return obj; return obj;
} }
@ -93,7 +96,7 @@ psyco_conn_close(connectionObject *self, PyObject *args)
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
if (!PyArg_ParseTuple(args, "")) return NULL; if (!PyArg_ParseTuple(args, "")) return NULL;
Dprintf("psyco_conn_close: closing connection at %p", self); Dprintf("psyco_conn_close: closing connection at %p", self);
conn_close(self); conn_close(self);
Dprintf("psyco_conn_close: connection at %p closed", self); Dprintf("psyco_conn_close: connection at %p closed", self);
@ -152,7 +155,7 @@ static PyObject *
psyco_conn_set_isolation_level(connectionObject *self, PyObject *args) psyco_conn_set_isolation_level(connectionObject *self, PyObject *args)
{ {
int level = 1; int level = 1;
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
if (!PyArg_ParseTuple(args, "i", &level)) return NULL; if (!PyArg_ParseTuple(args, "i", &level)) return NULL;
@ -162,7 +165,7 @@ psyco_conn_set_isolation_level(connectionObject *self, PyObject *args)
"isolation level out of bounds (0,3)"); "isolation level out of bounds (0,3)");
return NULL; return NULL;
} }
/* FIXME: check return status? */ /* FIXME: check return status? */
conn_switch_isolation_level(self, level); conn_switch_isolation_level(self, level);
@ -186,19 +189,19 @@ psyco_conn_set_client_encoding(connectionObject *self, PyObject *args)
EXC_IF_CONN_CLOSED(self); EXC_IF_CONN_CLOSED(self);
if (!PyArg_ParseTuple(args, "s", &enc)) return NULL; if (!PyArg_ParseTuple(args, "s", &enc)) return NULL;
/* convert to upper case and remove '-' and '_' from string */ /* convert to upper case and remove '-' and '_' from string */
buffer = PyMem_Malloc(strlen(enc)); buffer = PyMem_Malloc(strlen(enc));
for (i=j=0 ; i < strlen(enc) ; i++) { for (i=j=0 ; i < strlen(enc) ; i++) {
if (enc[i] == '_' || enc[i] == '-') if (enc[i] == '_' || enc[i] == '-')
continue; continue;
else else
buffer[j++] = toupper(enc[i]); buffer[j++] = toupper(enc[i]);
} }
buffer[j] = '\0'; buffer[j] = '\0';
if (conn_set_client_encoding(self, buffer) == 0) { if (conn_set_client_encoding(self, buffer) == 0) {
PyMem_Free(buffer); PyMem_Free(buffer);
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
@ -228,8 +231,8 @@ static struct PyMethodDef connectionObject_methods[] = {
{"set_isolation_level", (PyCFunction)psyco_conn_set_isolation_level, {"set_isolation_level", (PyCFunction)psyco_conn_set_isolation_level,
METH_VARARGS, psyco_conn_set_isolation_level_doc}, METH_VARARGS, psyco_conn_set_isolation_level_doc},
{"set_client_encoding", (PyCFunction)psyco_conn_set_client_encoding, {"set_client_encoding", (PyCFunction)psyco_conn_set_client_encoding,
METH_VARARGS, psyco_conn_set_client_encoding_doc}, METH_VARARGS, psyco_conn_set_client_encoding_doc},
#endif #endif
{NULL} {NULL}
}; };
@ -237,9 +240,9 @@ static struct PyMethodDef connectionObject_methods[] = {
static struct PyMemberDef connectionObject_members[] = { static struct PyMemberDef connectionObject_members[] = {
/* DBAPI-2.0 extensions (exception objects) */ /* DBAPI-2.0 extensions (exception objects) */
{"Error", T_OBJECT, {"Error", T_OBJECT,
offsetof(connectionObject, exc_Error), RO, Error_doc}, offsetof(connectionObject, exc_Error), RO, Error_doc},
{"Warning", {"Warning",
T_OBJECT, offsetof(connectionObject, exc_Warning), RO, Warning_doc}, T_OBJECT, offsetof(connectionObject, exc_Warning), RO, Warning_doc},
{"InterfaceError", T_OBJECT, {"InterfaceError", T_OBJECT,
offsetof(connectionObject, exc_InterfaceError), RO, offsetof(connectionObject, exc_InterfaceError), RO,
@ -262,7 +265,7 @@ static struct PyMemberDef connectionObject_members[] = {
{"NotSupportedError", T_OBJECT, {"NotSupportedError", T_OBJECT,
offsetof(connectionObject, exc_NotSupportedError), RO, offsetof(connectionObject, exc_NotSupportedError), RO,
NotSupportedError_doc}, NotSupportedError_doc},
#ifdef PSYCOPG_EXTENSIONS #ifdef PSYCOPG_EXTENSIONS
{"closed", T_LONG, offsetof(connectionObject, closed), RO, {"closed", T_LONG, offsetof(connectionObject, closed), RO,
"True if the connection is closed."}, "True if the connection is closed."},
{"isolation_level", T_LONG, {"isolation_level", T_LONG,
@ -274,14 +277,14 @@ static struct PyMemberDef connectionObject_members[] = {
{"notifies", T_OBJECT, offsetof(connectionObject, notifies), RO}, {"notifies", T_OBJECT, offsetof(connectionObject, notifies), RO},
{"dsn", T_STRING, offsetof(connectionObject, dsn), RO, {"dsn", T_STRING, offsetof(connectionObject, dsn), RO,
"The current connection string."}, "The current connection string."},
{"status", T_LONG, {"status", T_INT,
offsetof(connectionObject, status), RO, offsetof(connectionObject, status), RO,
"The current transaction status."}, "The current transaction status."},
{"string_types", T_OBJECT, offsetof(connectionObject, string_types), RO, {"string_types", T_OBJECT, offsetof(connectionObject, string_types), RO,
"A set of typecasters to convert textual values."}, "A set of typecasters to convert textual values."},
{"binary_types", T_OBJECT, offsetof(connectionObject, binary_types), RO, {"binary_types", T_OBJECT, offsetof(connectionObject, binary_types), RO,
"A set of typecasters to convert binary values."}, "A set of typecasters to convert binary values."},
#endif #endif
{NULL} {NULL}
}; };
@ -293,9 +296,11 @@ connection_setup(connectionObject *self, char *dsn)
char *pos; char *pos;
int res; int res;
Dprintf("connection_setup: init connection object at %p, refcnt = %d", Dprintf("connection_setup: init connection object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
self->dsn = strdup(dsn); self->dsn = strdup(dsn);
self->notice_list = PyList_New(0); self->notice_list = PyList_New(0);
self->notifies = PyList_New(0); self->notifies = PyList_New(0);
@ -305,21 +310,23 @@ connection_setup(connectionObject *self, char *dsn)
self->async_cursor = NULL; self->async_cursor = NULL;
self->pgconn = NULL; self->pgconn = NULL;
self->mark = 0; self->mark = 0;
self->string_types = PyDict_New(); self->string_types = PyDict_New();
self->binary_types = PyDict_New(); self->binary_types = PyDict_New();
pthread_mutex_init(&(self->lock), NULL); pthread_mutex_init(&(self->lock), NULL);
if (conn_connect(self) != 0) { if (conn_connect(self) != 0) {
Dprintf("connection_init: FAILED"); Dprintf("connection_init: FAILED");
res = -1; res = -1;
} }
else { else {
Dprintf("connection_setup: good connection object at %p, refcnt = %d", Dprintf("connection_setup: good connection object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
res = 0; res = 0;
} }
/* here we obfuscate the password even if there was a connection error */ /* here we obfuscate the password even if there was a connection error */
pos = strstr(self->dsn, "password"); pos = strstr(self->dsn, "password");
if (pos != NULL) { if (pos != NULL) {
@ -336,21 +343,23 @@ connection_dealloc(PyObject* obj)
connectionObject *self = (connectionObject *)obj; connectionObject *self = (connectionObject *)obj;
if (self->closed == 0) conn_close(self); if (self->closed == 0) conn_close(self);
if (self->dsn) free(self->dsn); if (self->dsn) free(self->dsn);
if (self->encoding) PyMem_Free(self->encoding); if (self->encoding) PyMem_Free(self->encoding);
if (self->critical) free(self->critical); if (self->critical) free(self->critical);
Py_XDECREF(self->notice_list); Py_XDECREF(self->notice_list);
Py_XDECREF(self->notifies); Py_XDECREF(self->notifies);
Py_XDECREF(self->async_cursor); Py_XDECREF(self->async_cursor);
Py_XDECREF(self->string_types); Py_XDECREF(self->string_types);
Py_XDECREF(self->binary_types); Py_XDECREF(self->binary_types);
pthread_mutex_destroy(&(self->lock)); pthread_mutex_destroy(&(self->lock));
Dprintf("connection_dealloc: deleted connection object at %p, refcnt = %d", Dprintf("connection_dealloc: deleted connection object at %p, refcnt = "
obj, obj->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
obj, obj->ob_refcnt
);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -403,7 +412,7 @@ PyTypeObject connectionType = {
sizeof(connectionObject), sizeof(connectionObject),
0, 0,
connection_dealloc, /*tp_dealloc*/ connection_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
@ -421,7 +430,7 @@ PyTypeObject connectionType = {
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
connectionType_doc, /*tp_doc*/ connectionType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -438,11 +447,11 @@ PyTypeObject connectionType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
connection_init, /*tp_init*/ connection_init, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
connection_new, /*tp_new*/ connection_new, /*tp_new*/

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_CURSOR_H #ifndef PSYCOPG_CURSOR_H
#define PSYCOPG_CURSOR_H 1 #define PSYCOPG_CURSOR_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <libpq-fe.h> #include <libpq-fe.h>
@ -41,7 +42,7 @@ typedef struct {
int closed:1; /* 1 if the cursor is closed */ int closed:1; /* 1 if the cursor is closed */
int notuples:1; /* 1 if the command was not a SELECT query */ int notuples:1; /* 1 if the command was not a SELECT query */
int needsfetch:1; /* 1 if a call to pq_fetch is pending */ int needsfetch:1; /* 1 if a call to pq_fetch is pending */
long int rowcount; /* number of rows affected by last execute */ long int rowcount; /* number of rows affected by last execute */
long int columns; /* number of columns fetched from the db */ long int columns; /* number of columns fetched from the db */
long int arraysize; /* how many rows should fetchmany() return */ long int arraysize; /* how many rows should fetchmany() return */
@ -58,28 +59,28 @@ typedef struct {
PyObject *casts; /* an array (tuple) of typecast functions */ PyObject *casts; /* an array (tuple) of typecast functions */
PyObject *caster; /* the current typecaster object */ PyObject *caster; /* the current typecaster object */
PyObject *copyfile; /* file-like used during COPY TO/FROM ops */ PyObject *copyfile; /* file-like used during COPY TO/FROM ops */
long int copysize; /* size of the copy buffer during COPY TO/FROM ops */ Py_ssize_t copysize; /* size of the copy buffer during COPY TO/FROM ops */
#define DEFAULT_COPYSIZE 16384 #define DEFAULT_COPYSIZE 16384
PyObject *tuple_factory; /* factory for result tuples */ PyObject *tuple_factory; /* factory for result tuples */
PyObject *tzinfo_factory; /* factory for tzinfo objects */ PyObject *tzinfo_factory; /* factory for tzinfo objects */
PyObject *query; /* last query executed */ PyObject *query; /* last query executed */
char *qattr; /* quoting attr, used when quoting strings */ char *qattr; /* quoting attr, used when quoting strings */
char *notice; /* a notice from the backend */ char *notice; /* a notice from the backend */
char *name; /* this cursor name */ char *name; /* this cursor name */
PyObject *string_types; /* a set of typecasters for string types */ PyObject *string_types; /* a set of typecasters for string types */
PyObject *binary_types; /* a set of typecasters for binary types */ PyObject *binary_types; /* a set of typecasters for binary types */
} cursorObject; } cursorObject;
/* C-callable functions in cursor_int.c and cursor_ext.c */ /* C-callable functions in cursor_int.c and cursor_ext.c */
extern void curs_reset(cursorObject *self); extern void curs_reset(cursorObject *self);
/* exception-raising macros */ /* exception-raising macros */
#define EXC_IF_CURS_CLOSED(self) \ #define EXC_IF_CURS_CLOSED(self) \
if ((self)->closed || ((self)->conn && (self)->conn->closed)) { \ if ((self)->closed || ((self)->conn && (self)->conn->closed)) { \
@ -90,7 +91,7 @@ if ((self)->closed || ((self)->conn && (self)->conn->closed)) { \
if ((self)->notuples && (self)->name == NULL) { \ if ((self)->notuples && (self)->name == NULL) { \
PyErr_SetString(ProgrammingError, "no results to fetch"); \ PyErr_SetString(ProgrammingError, "no results to fetch"); \
return NULL; } return NULL; }
#define EXC_IF_NO_MARK(self) \ #define EXC_IF_NO_MARK(self) \
if ((self)->mark != (self)->conn->mark) { \ if ((self)->mark != (self)->conn->mark) { \
PyErr_SetString(ProgrammingError, "named cursor isn't valid anymore"); \ PyErr_SetString(ProgrammingError, "named cursor isn't valid anymore"); \

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <string.h> #include <string.h>

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <string.h> #include <string.h>
@ -49,12 +50,12 @@ static PyObject *
psyco_curs_close(cursorObject *self, PyObject *args) psyco_curs_close(cursorObject *self, PyObject *args)
{ {
if (!PyArg_ParseTuple(args, "")) return NULL; if (!PyArg_ParseTuple(args, "")) return NULL;
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
if (self->name != NULL) { if (self->name != NULL) {
char buffer[128]; char buffer[128];
EXC_IF_NO_MARK(self); EXC_IF_NO_MARK(self);
PyOS_snprintf(buffer, 127, "CLOSE %s", self->name); PyOS_snprintf(buffer, 127, "CLOSE %s", self->name);
if (pq_execute(self, buffer, 0) == -1) return NULL; if (pq_execute(self, buffer, 0) == -1) return NULL;
@ -91,7 +92,7 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
if (c[0] == '%' && c[1] == '%') { if (c[0] == '%' && c[1] == '%') {
c+=2; force = 1; c+=2; force = 1;
} }
/* if we find '%(' then this is a dictionary, we: /* if we find '%(' then this is a dictionary, we:
1/ find the matching ')' and extract the key name 1/ find the matching ')' and extract the key name
2/ locate the value in the dictionary (or return an error) 2/ locate the value in the dictionary (or return an error)
@ -107,7 +108,7 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
key = PyString_FromStringAndSize(c+2, d-c-2); key = PyString_FromStringAndSize(c+2, d-c-2);
value = PyObject_GetItem(var, key); value = PyObject_GetItem(var, key);
/* key has refcnt 1, value the original value + 1 */ /* key has refcnt 1, value the original value + 1 */
/* if value is NULL we did not find the key (or this is not a /* if value is NULL we did not find the key (or this is not a
dictionary): let python raise a KeyError */ dictionary): let python raise a KeyError */
if (value == NULL) { if (value == NULL) {
@ -116,12 +117,13 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
return -1; return -1;
} }
Dprintf("_mogrify: value refcnt: %d (+1)", value->ob_refcnt); Dprintf("_mogrify: value refcnt: "
FORMAT_CODE_PY_SSIZE_T " (+1)", value->ob_refcnt);
if (n == NULL) { if (n == NULL) {
n = PyDict_New(); n = PyDict_New();
} }
if ((item = PyObject_GetItem(n, key)) == NULL) { if ((item = PyObject_GetItem(n, key)) == NULL) {
PyObject *t = NULL; PyObject *t = NULL;
@ -134,7 +136,7 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
t = PyString_FromString("NULL"); t = PyString_FromString("NULL");
PyDict_SetItem(n, key, t); PyDict_SetItem(n, key, t);
/* t is a new object, refcnt = 1, key is at 2 */ /* t is a new object, refcnt = 1, key is at 2 */
/* if the value is None we need to substitute the /* if the value is None we need to substitute the
formatting char with 's' (FIXME: this should not be formatting char with 's' (FIXME: this should not be
necessary if we drop support for formats other than necessary if we drop support for formats other than
@ -151,7 +153,7 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
} }
else { else {
/* no adapter found, raise a BIG exception */ /* no adapter found, raise a BIG exception */
Py_XDECREF(value); Py_XDECREF(value);
Py_DECREF(n); Py_DECREF(n);
return -1; return -1;
} }
@ -160,26 +162,29 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
Py_XDECREF(t); /* t dies here */ Py_XDECREF(t); /* t dies here */
/* after the DECREF value has the original refcnt plus 1 /* after the DECREF value has the original refcnt plus 1
if it was added to the dictionary directly; good */ if it was added to the dictionary directly; good */
Py_XDECREF(value); Py_XDECREF(value);
} }
else { else {
/* we have an item with one extra refcnt here, zap! */ /* we have an item with one extra refcnt here, zap! */
Py_DECREF(item); Py_DECREF(item);
} }
Py_DECREF(key); /* key has the original refcnt now */ Py_DECREF(key); /* key has the original refcnt now */
Dprintf("_mogrify: after value refcnt: %d",value->ob_refcnt); Dprintf("_mogrify: after value refcnt: "
FORMAT_CODE_PY_SSIZE_T,
value->ob_refcnt
);
} }
c = d; c = d;
} }
else if (c[0] == '%' && c[1] != '(') { else if (c[0] == '%' && c[1] != '(') {
/* this is a format that expects a tuple; it is much easier, /* this is a format that expects a tuple; it is much easier,
because we don't need to check the old/new dictionary for because we don't need to check the old/new dictionary for
keys */ keys */
value = PySequence_GetItem(var, index); value = PySequence_GetItem(var, index);
/* value has refcnt inc'ed by 1 here */ /* value has refcnt inc'ed by 1 here */
/* if value is NULL this is not a sequence or the index is wrong; /* if value is NULL this is not a sequence or the index is wrong;
anyway we let python set its own exception */ anyway we let python set its own exception */
if (value == NULL) { if (value == NULL) {
@ -190,10 +195,10 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
if (n == NULL) { if (n == NULL) {
n = PyTuple_New(PyObject_Length(var)); n = PyTuple_New(PyObject_Length(var));
} }
/* let's have d point just after the '%' */ /* let's have d point just after the '%' */
d = c+1; d = c+1;
if (value == Py_None) { if (value == Py_None) {
PyTuple_SET_ITEM(n, index, PyString_FromString("NULL")); PyTuple_SET_ITEM(n, index, PyString_FromString("NULL"));
while (*d && !isalpha(*d)) d++; while (*d && !isalpha(*d)) d++;
@ -224,10 +229,10 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
if (force && n == NULL) if (force && n == NULL)
n = PyTuple_New(0); n = PyTuple_New(0);
*new = n; *new = n;
return 0; return 0;
} }
#define psyco_curs_execute_doc \ #define psyco_curs_execute_doc \
"execute(query, vars=None, async=0) -- Execute query with bound vars." "execute(query, vars=None, async=0) -- Execute query with bound vars."
@ -237,7 +242,7 @@ _psyco_curs_execute(cursorObject *self,
{ {
int res; int res;
PyObject *fquery, *cvt = NULL, *uoperation = NULL; PyObject *fquery, *cvt = NULL, *uoperation = NULL;
pthread_mutex_lock(&(self->conn->lock)); pthread_mutex_lock(&(self->conn->lock));
if (self->conn->async_cursor != NULL if (self->conn->async_cursor != NULL
&& self->conn->async_cursor != (PyObject*)self) { && self->conn->async_cursor != (PyObject*)self) {
@ -247,18 +252,18 @@ _psyco_curs_execute(cursorObject *self,
return 0; return 0;
} }
pthread_mutex_unlock(&(self->conn->lock)); pthread_mutex_unlock(&(self->conn->lock));
if (!PyObject_IsTrue(operation)) { if (!PyObject_IsTrue(operation)) {
psyco_set_error(ProgrammingError, (PyObject*)self, psyco_set_error(ProgrammingError, (PyObject*)self,
"can't execute an empty query", NULL, NULL); "can't execute an empty query", NULL, NULL);
return 0; return 0;
} }
if (PyUnicode_Check(operation)) { if (PyUnicode_Check(operation)) {
PyObject *enc = PyDict_GetItemString(psycoEncodings, PyObject *enc = PyDict_GetItemString(psycoEncodings,
self->conn->encoding); self->conn->encoding);
/* enc is a borrowed reference, we won't decref it */ /* enc is a borrowed reference, we won't decref it */
if (enc) { if (enc) {
operation = PyUnicode_AsEncodedString( operation = PyUnicode_AsEncodedString(
operation, PyString_AsString(enc), NULL); operation, PyString_AsString(enc), NULL);
@ -267,7 +272,7 @@ _psyco_curs_execute(cursorObject *self,
target encoding we just let the exception propagate */ target encoding we just let the exception propagate */
if (operation == NULL) return 0; if (operation == NULL) return 0;
/* we clone operation in uoperation to be sure to free it later */ /* we clone operation in uoperation to be sure to free it later */
uoperation = operation; uoperation = operation;
} }
else { else {
@ -282,20 +287,20 @@ _psyco_curs_execute(cursorObject *self,
"argument 1 must be a string or unicode object"); "argument 1 must be a string or unicode object");
return 0; return 0;
} }
IFCLEARPGRES(self->pgres); IFCLEARPGRES(self->pgres);
if (self->query) { if (self->query) {
Py_DECREF(self->query); Py_DECREF(self->query);
self->query = NULL; self->query = NULL;
} }
Dprintf("psyco_curs_execute: starting execution of new query"); Dprintf("psyco_curs_execute: starting execution of new query");
/* here we are, and we have a sequence or a dictionary filled with /* here we are, and we have a sequence or a dictionary filled with
objects to be substituted (bound variables). we try to be smart and do objects to be substituted (bound variables). we try to be smart and do
the right thing (i.e., what the user expects) */ the right thing (i.e., what the user expects) */
if (vars && vars != Py_None) if (vars && vars != Py_None)
{ {
if(_mogrify(vars, operation, self->conn, &cvt) == -1) { if(_mogrify(vars, operation, self->conn, &cvt) == -1) {
@ -315,13 +320,13 @@ _psyco_curs_execute(cursorObject *self,
and return the appropriate ProgrammingError. we do that by grabbing and return the appropriate ProgrammingError. we do that by grabbing
the curren exception (we will later restore it if the type or the the curren exception (we will later restore it if the type or the
strings do not match.) */ strings do not match.) */
if (!(fquery = PyString_Format(operation, cvt))) { if (!(fquery = PyString_Format(operation, cvt))) {
PyObject *err, *arg, *trace; PyObject *err, *arg, *trace;
int pe = 0; int pe = 0;
PyErr_Fetch(&err, &arg, &trace); PyErr_Fetch(&err, &arg, &trace);
if (err && PyErr_GivenExceptionMatches(err, PyExc_TypeError)) { if (err && PyErr_GivenExceptionMatches(err, PyExc_TypeError)) {
Dprintf("psyco_curs_execute: TypeError exception catched"); Dprintf("psyco_curs_execute: TypeError exception catched");
PyErr_NormalizeException(&err, &arg, &trace); PyErr_NormalizeException(&err, &arg, &trace);
@ -356,7 +361,7 @@ _psyco_curs_execute(cursorObject *self,
Py_XDECREF(uoperation); Py_XDECREF(uoperation);
return 0; return 0;
} }
if (self->name != NULL) { if (self->name != NULL) {
self->query = PyString_FromFormat( self->query = PyString_FromFormat(
"DECLARE %s CURSOR WITHOUT HOLD FOR %s", "DECLARE %s CURSOR WITHOUT HOLD FOR %s",
@ -366,8 +371,9 @@ _psyco_curs_execute(cursorObject *self,
else { else {
self->query = fquery; self->query = fquery;
} }
Dprintf("psyco_curs_execute: cvt->refcnt = %d", cvt->ob_refcnt); Dprintf("psyco_curs_execute: cvt->refcnt = " FORMAT_CODE_PY_SSIZE_T,
cvt->ob_refcnt);
Py_DECREF(cvt); Py_DECREF(cvt);
} }
else { else {
@ -381,25 +387,25 @@ _psyco_curs_execute(cursorObject *self,
self->query = operation; self->query = operation;
} }
} }
res = pq_execute(self, PyString_AS_STRING(self->query), async); res = pq_execute(self, PyString_AS_STRING(self->query), async);
Dprintf("psyco_curs_execute: res = %d, pgres = %p", res, self->pgres); Dprintf("psyco_curs_execute: res = %d, pgres = %p", res, self->pgres);
Py_XDECREF(uoperation); Py_XDECREF(uoperation);
return res == -1 ? 0 : 1; return res == -1 ? 0 : 1;
} }
static PyObject * static PyObject *
psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs) psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
{ {
long int async = 0; long int async = 0;
PyObject *vars = NULL, *operation = NULL; PyObject *vars = NULL, *operation = NULL;
static char *kwlist[] = {"query", "vars", "async", NULL}; static char *kwlist[] = {"query", "vars", "async", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ol", kwlist,
&operation, &vars, &async)) { &operation, &vars, &async)) {
return NULL; return NULL;
} }
@ -414,7 +420,7 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
if (self->conn->isolation_level == 0) { if (self->conn->isolation_level == 0) {
psyco_set_error(ProgrammingError, (PyObject*)self, psyco_set_error(ProgrammingError, (PyObject*)self,
"can't use a named cursor outside of transactions", NULL, NULL); "can't use a named cursor outside of transactions", NULL, NULL);
return NULL; return NULL;
} }
if (self->conn->mark != self->mark) { if (self->conn->mark != self->mark) {
psyco_set_error(ProgrammingError, (PyObject*)self, psyco_set_error(ProgrammingError, (PyObject*)self,
@ -424,7 +430,7 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
} }
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
if (_psyco_curs_execute(self, operation, vars, async)) { if (_psyco_curs_execute(self, operation, vars, async)) {
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
@ -442,7 +448,7 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
{ {
PyObject *operation = NULL, *vars = NULL; PyObject *operation = NULL, *vars = NULL;
PyObject *v, *iter = NULL; PyObject *v, *iter = NULL;
static char *kwlist[] = {"query", "vars_list", NULL}; static char *kwlist[] = {"query", "vars_list", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist,
@ -451,18 +457,18 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
} }
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
if (self->name != NULL) { if (self->name != NULL) {
psyco_set_error(ProgrammingError, (PyObject*)self, psyco_set_error(ProgrammingError, (PyObject*)self,
"can't call .executemany() on named cursors", NULL, NULL); "can't call .executemany() on named cursors", NULL, NULL);
return NULL; return NULL;
} }
if (!PyIter_Check(vars)) { if (!PyIter_Check(vars)) {
vars = iter = PyObject_GetIter(vars); vars = iter = PyObject_GetIter(vars);
if (iter == NULL) return NULL; if (iter == NULL) return NULL;
} }
while ((v = PyIter_Next(vars)) != NULL) { while ((v = PyIter_Next(vars)) != NULL) {
if (_psyco_curs_execute(self, operation, v, 0) == 0) { if (_psyco_curs_execute(self, operation, v, 0) == 0) {
Py_DECREF(v); Py_DECREF(v);
@ -473,7 +479,7 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
} }
} }
Py_XDECREF(iter); Py_XDECREF(iter);
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
@ -485,10 +491,10 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
static PyObject * static PyObject *
psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs) psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs)
{ {
PyObject *vars = NULL, *cvt = NULL, *operation = NULL; PyObject *vars = NULL, *cvt = NULL, *operation = NULL;
PyObject *fquery; PyObject *fquery;
static char *kwlist[] = {"query", "vars", NULL}; static char *kwlist[] = {"query", "vars", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist,
@ -501,7 +507,7 @@ psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs)
"unicode queries not yet supported"); "unicode queries not yet supported");
return NULL; return NULL;
} }
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
IFCLEARPGRES(self->pgres); IFCLEARPGRES(self->pgres);
@ -516,13 +522,13 @@ psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs)
if(_mogrify(vars, operation, self->conn, &cvt) == -1) return NULL; if(_mogrify(vars, operation, self->conn, &cvt) == -1) return NULL;
} }
if (vars && cvt) { if (vars && cvt) {
if (!(fquery = PyString_Format(operation, cvt))) { if (!(fquery = PyString_Format(operation, cvt))) {
PyObject *err, *arg, *trace; PyObject *err, *arg, *trace;
int pe = 0; int pe = 0;
PyErr_Fetch(&err, &arg, &trace); PyErr_Fetch(&err, &arg, &trace);
if (err && PyErr_GivenExceptionMatches(err, PyExc_TypeError)) { if (err && PyErr_GivenExceptionMatches(err, PyExc_TypeError)) {
Dprintf("psyco_curs_execute: TypeError exception catched"); Dprintf("psyco_curs_execute: TypeError exception catched");
PyErr_NormalizeException(&err, &arg, &trace); PyErr_NormalizeException(&err, &arg, &trace);
@ -557,8 +563,10 @@ psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs)
return NULL; return NULL;
} }
Dprintf("psyco_curs_execute: cvt->refcnt = %d, fquery->refcnt = %d", Dprintf("psyco_curs_execute: cvt->refcnt = " FORMAT_CODE_PY_SSIZE_T
cvt->ob_refcnt, fquery->ob_refcnt); ", fquery->refcnt = " FORMAT_CODE_PY_SSIZE_T,
cvt->ob_refcnt, fquery->ob_refcnt
);
Py_DECREF(cvt); Py_DECREF(cvt);
} }
else { else {
@ -583,7 +591,7 @@ static int
_psyco_curs_prefetch(cursorObject *self) _psyco_curs_prefetch(cursorObject *self)
{ {
int i = 0; int i = 0;
/* check if the fetching cursor is the one that did the asynchronous query /* check if the fetching cursor is the one that did the asynchronous query
and raise an exception if not */ and raise an exception if not */
pthread_mutex_lock(&(self->conn->lock)); pthread_mutex_lock(&(self->conn->lock));
@ -595,7 +603,7 @@ _psyco_curs_prefetch(cursorObject *self)
return -2; return -2;
} }
pthread_mutex_unlock(&(self->conn->lock)); pthread_mutex_unlock(&(self->conn->lock));
if (self->pgres == NULL || self->needsfetch) { if (self->pgres == NULL || self->needsfetch) {
self->needsfetch = 0; self->needsfetch = 0;
Dprintf("_psyco_curs_prefetch: trying to fetch data"); Dprintf("_psyco_curs_prefetch: trying to fetch data");
@ -616,7 +624,7 @@ _psyco_curs_buildrow_fill(cursorObject *self, PyObject *res,
int i, len; int i, len;
unsigned char *str; unsigned char *str;
PyObject *val; PyObject *val;
for (i=0; i < n; i++) { for (i=0; i < n; i++) {
if (PQgetisnull(self->pgres, row, i)) { if (PQgetisnull(self->pgres, row, i)) {
str = NULL; str = NULL;
@ -634,7 +642,10 @@ _psyco_curs_buildrow_fill(cursorObject *self, PyObject *res,
(PyObject*)self); (PyObject*)self);
if (val) { if (val) {
Dprintf("_psyco_curs_buildrow: val->refcnt = %d", val->ob_refcnt); Dprintf("_psyco_curs_buildrow: val->refcnt = "
FORMAT_CODE_PY_SSIZE_T,
val->ob_refcnt
);
if (istuple) { if (istuple) {
PyTuple_SET_ITEM(res, i, val); PyTuple_SET_ITEM(res, i, val);
} }
@ -659,7 +670,7 @@ static PyObject *
_psyco_curs_buildrow(cursorObject *self, int row) _psyco_curs_buildrow(cursorObject *self, int row)
{ {
int n; int n;
n = PQnfields(self->pgres); n = PQnfields(self->pgres);
return _psyco_curs_buildrow_fill(self, PyTuple_New(n), row, n, 1); return _psyco_curs_buildrow_fill(self, PyTuple_New(n), row, n, 1);
} }
@ -681,24 +692,24 @@ PyObject *
psyco_curs_fetchone(cursorObject *self, PyObject *args) psyco_curs_fetchone(cursorObject *self, PyObject *args)
{ {
PyObject *res; PyObject *res;
if (args && !PyArg_ParseTuple(args, "")) return NULL; if (args && !PyArg_ParseTuple(args, "")) return NULL;
EXC_IF_CURS_CLOSED(self) EXC_IF_CURS_CLOSED(self)
if (_psyco_curs_prefetch(self) < 0) return NULL; if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self); EXC_IF_NO_TUPLES(self);
if (self->name != NULL) { if (self->name != NULL) {
char buffer[128]; char buffer[128];
EXC_IF_NO_MARK(self); EXC_IF_NO_MARK(self);
PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM %s", self->name); PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM %s", self->name);
if (pq_execute(self, buffer, 0) == -1) return NULL; if (pq_execute(self, buffer, 0) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) return NULL; if (_psyco_curs_prefetch(self) < 0) return NULL;
} }
Dprintf("psyco_curs_fetchone: fetching row %ld", self->row); Dprintf("psyco_curs_fetchone: fetching row %ld", self->row);
Dprintf("psyco_curs_fetchone: rowcount = %ld", self->rowcount); Dprintf("psyco_curs_fetchone: rowcount = %ld", self->rowcount);
if (self->row >= self->rowcount) { if (self->row >= self->rowcount) {
/* we exausted available data: return None */ /* we exausted available data: return None */
@ -710,7 +721,7 @@ psyco_curs_fetchone(cursorObject *self, PyObject *args)
res = _psyco_curs_buildrow(self, self->row); res = _psyco_curs_buildrow(self, self->row);
else else
res = _psyco_curs_buildrow_with_factory(self, self->row); res = _psyco_curs_buildrow_with_factory(self, self->row);
self->row++; /* move the counter to next line */ self->row++; /* move the counter to next line */
/* if the query was async aggresively free pgres, to allow /* if the query was async aggresively free pgres, to allow
@ -736,10 +747,10 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
{ {
int i; int i;
PyObject *list, *res; PyObject *list, *res;
long int size = self->arraysize; long int size = self->arraysize;
static char *kwlist[] = {"size", NULL}; static char *kwlist[] = {"size", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwords, "|l", kwlist, &size)) { if (!PyArg_ParseTupleAndKeywords(args, kwords, "|l", kwlist, &size)) {
return NULL; return NULL;
} }
@ -750,7 +761,7 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
if (self->name != NULL) { if (self->name != NULL) {
char buffer[128]; char buffer[128];
EXC_IF_NO_MARK(self); EXC_IF_NO_MARK(self);
PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM %s", PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM %s",
(int)size, self->name); (int)size, self->name);
@ -764,19 +775,19 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
} }
Dprintf("psyco_curs_fetchmany: size = %ld", size); Dprintf("psyco_curs_fetchmany: size = %ld", size);
if (size <= 0) { if (size <= 0) {
return PyList_New(0); return PyList_New(0);
} }
list = PyList_New(size); list = PyList_New(size);
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
if (self->tuple_factory == Py_None) if (self->tuple_factory == Py_None)
res = _psyco_curs_buildrow(self, self->row); res = _psyco_curs_buildrow(self, self->row);
else else
res = _psyco_curs_buildrow_with_factory(self, self->row); res = _psyco_curs_buildrow_with_factory(self, self->row);
self->row++; self->row++;
if (res == NULL) { if (res == NULL) {
@ -792,7 +803,7 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
if (self->row >= self->rowcount if (self->row >= self->rowcount
&& self->conn->async_cursor == (PyObject*)self) && self->conn->async_cursor == (PyObject*)self)
IFCLEARPGRES(self->pgres); IFCLEARPGRES(self->pgres);
return list; return list;
} }
@ -819,10 +830,10 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args)
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
if (_psyco_curs_prefetch(self) < 0) return NULL; if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self); EXC_IF_NO_TUPLES(self);
if (self->name != NULL) { if (self->name != NULL) {
char buffer[128]; char buffer[128];
EXC_IF_NO_MARK(self); EXC_IF_NO_MARK(self);
PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM %s", self->name); PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM %s", self->name);
if (pq_execute(self, buffer, 0) == -1) return NULL; if (pq_execute(self, buffer, 0) == -1) return NULL;
@ -830,19 +841,19 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args)
} }
size = self->rowcount - self->row; size = self->rowcount - self->row;
if (size <= 0) { if (size <= 0) {
return PyList_New(0); return PyList_New(0);
} }
list = PyList_New(size); list = PyList_New(size);
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
if (self->tuple_factory == Py_None) if (self->tuple_factory == Py_None)
res = _psyco_curs_buildrow(self, self->row); res = _psyco_curs_buildrow(self, self->row);
else else
res = _psyco_curs_buildrow_with_factory(self, self->row); res = _psyco_curs_buildrow_with_factory(self, self->row);
self->row++; self->row++;
if (res == NULL) { if (res == NULL) {
@ -858,7 +869,7 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args)
if (self->row >= self->rowcount if (self->row >= self->rowcount
&& self->conn->async_cursor == (PyObject*)self) && self->conn->async_cursor == (PyObject*)self)
IFCLEARPGRES(self->pgres); IFCLEARPGRES(self->pgres);
return list; return list;
} }
@ -878,7 +889,7 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
PyObject *operation = NULL; PyObject *operation = NULL;
PyObject *res = NULL; PyObject *res = NULL;
if (!PyArg_ParseTuple(args, "s|Oi", &procname, &parameters, &async)) { if (!PyArg_ParseTuple(args, "s|Ol", &procname, &parameters, &async)) {
return NULL; return NULL;
} }
@ -888,28 +899,28 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
psyco_set_error(ProgrammingError, (PyObject*)self, psyco_set_error(ProgrammingError, (PyObject*)self,
"can't call .callproc() on named cursors", NULL, NULL); "can't call .callproc() on named cursors", NULL, NULL);
return NULL; return NULL;
} }
if(parameters && parameters != Py_None) { if(parameters && parameters != Py_None) {
nparameters = PyObject_Length(parameters); nparameters = PyObject_Length(parameters);
if (nparameters < 0) nparameters = 0; if (nparameters < 0) nparameters = 0;
} }
/* allocate some memory, build the SQL and create a PyString from it */ /* allocate some memory, build the SQL and create a PyString from it */
sl = strlen(procname) + 17 + nparameters*3 - (nparameters ? 1 : 0); sl = strlen(procname) + 17 + nparameters*3 - (nparameters ? 1 : 0);
sql = (char*)PyMem_Malloc(sl); sql = (char*)PyMem_Malloc(sl);
if (sql == NULL) return NULL; if (sql == NULL) return NULL;
sprintf(sql, "SELECT * FROM %s(", procname); sprintf(sql, "SELECT * FROM %s(", procname);
for(i=0; i<nparameters; i++) { for(i=0; i<nparameters; i++) {
strcat(sql, "%s,"); strcat(sql, "%s,");
} }
sql[sl-2] = ')'; sql[sl-2] = ')';
sql[sl-1] = '\0'; sql[sl-1] = '\0';
operation = PyString_FromString(sql); operation = PyString_FromString(sql);
PyMem_Free((void*)sql); PyMem_Free((void*)sql);
if (_psyco_curs_execute(self, operation, parameters, async)) { if (_psyco_curs_execute(self, operation, parameters, async)) {
Py_INCREF(Py_None); Py_INCREF(Py_None);
res = Py_None; res = Py_None;
@ -931,7 +942,7 @@ static PyObject *
psyco_curs_nextset(cursorObject *self, PyObject *args) psyco_curs_nextset(cursorObject *self, PyObject *args)
{ {
if (!PyArg_ParseTuple(args, "")) return NULL; if (!PyArg_ParseTuple(args, "")) return NULL;
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
PyErr_SetString(NotSupportedError, "not supported by PostgreSQL"); PyErr_SetString(NotSupportedError, "not supported by PostgreSQL");
@ -949,10 +960,10 @@ static PyObject *
psyco_curs_setinputsizes(cursorObject *self, PyObject *args) psyco_curs_setinputsizes(cursorObject *self, PyObject *args)
{ {
PyObject *sizes; PyObject *sizes;
if (!PyArg_ParseTuple(args, "O", &sizes)) if (!PyArg_ParseTuple(args, "O", &sizes))
return NULL; return NULL;
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
Py_INCREF(Py_None); Py_INCREF(Py_None);
@ -970,10 +981,10 @@ static PyObject *
psyco_curs_setoutputsize(cursorObject *self, PyObject *args) psyco_curs_setoutputsize(cursorObject *self, PyObject *args)
{ {
long int size, column; long int size, column;
if (!PyArg_ParseTuple(args, "l|l", &size, &column)) if (!PyArg_ParseTuple(args, "l|l", &size, &column))
return NULL; return NULL;
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
Py_INCREF(Py_None); Py_INCREF(Py_None);
@ -984,7 +995,7 @@ psyco_curs_setoutputsize(cursorObject *self, PyObject *args)
/* scroll - scroll position in result list */ /* scroll - scroll position in result list */
#define psyco_curs_scroll_doc \ #define psyco_curs_scroll_doc \
"scroll(value, mode='relative') -- Scroll to new position according to mode." "scroll(value, mode='relative') -- Scroll to new position according to mode."
static PyObject * static PyObject *
psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs) psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
@ -997,7 +1008,7 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|s", if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|s",
kwlist, &value, &mode)) kwlist, &value, &mode))
return NULL; return NULL;
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
/* if the cursor is not named we have the full result set and we can do /* if the cursor is not named we have the full result set and we can do
@ -1013,21 +1024,21 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
"scroll mode must be 'relative' or 'absolute'", NULL, NULL); "scroll mode must be 'relative' or 'absolute'", NULL, NULL);
return NULL; return NULL;
} }
if (newpos < 0 || newpos >= self->rowcount ) { if (newpos < 0 || newpos >= self->rowcount ) {
psyco_set_error(ProgrammingError, (PyObject*)self, psyco_set_error(ProgrammingError, (PyObject*)self,
"scroll destination out of bounds", NULL, NULL); "scroll destination out of bounds", NULL, NULL);
return NULL; return NULL;
} }
self->row = newpos; self->row = newpos;
} }
else { else {
char buffer[128]; char buffer[128];
EXC_IF_NO_MARK(self); EXC_IF_NO_MARK(self);
if (strcmp(mode, "absolute") == 0) { if (strcmp(mode, "absolute") == 0) {
PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM %s", PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM %s",
value, self->name); value, self->name);
@ -1064,7 +1075,7 @@ _psyco_curs_has_read_check(PyObject* o, void* var)
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"argument 1 must have both .read() and .readline() methods"); "argument 1 must have both .read() and .readline() methods");
return 0; return 0;
} }
} }
static PyObject * static PyObject *
@ -1073,20 +1084,22 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
char query[1024]; char query[1024];
char *table_name; char *table_name;
char *sep = "\t", *null = NULL; char *sep = "\t", *null = NULL;
long int bufsize = DEFAULT_COPYSIZE; Py_ssize_t bufsize = DEFAULT_COPYSIZE;
PyObject *file, *columns = NULL, *res = NULL; PyObject *file, *columns = NULL, *res = NULL;
char columnlist[1024] = ""; char columnlist[1024] = "";
static char *kwlist[] = {"file", "table", "sep", "null", "size", static char *kwlist[] = {"file", "table", "sep", "null", "size",
"columns", NULL}; "columns", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ssiO", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwargs,
_psyco_curs_has_read_check, &file, "O&s|ss" CONV_CODE_PY_SSIZE_T "O", kwlist,
&table_name, &sep, &null, &bufsize, _psyco_curs_has_read_check, &file, &table_name, &sep, &null, &bufsize,
&columns)) { &columns)
)
{
return NULL; return NULL;
} }
if (columns != NULL && columns != Py_None) { if (columns != NULL && columns != Py_None) {
PyObject* collistiter = PyObject_GetIter(columns); PyObject* collistiter = PyObject_GetIter(columns);
PyObject* col; PyObject* col;
@ -1102,7 +1115,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
Py_DECREF(col); Py_DECREF(col);
Py_DECREF(collistiter); Py_DECREF(collistiter);
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"Elements in column list must be strings"); "Elements in column list must be strings");
return NULL; return NULL;
} }
PyString_AsStringAndSize(col, &colname, &colitemlen); PyString_AsStringAndSize(col, &colname, &colitemlen);
@ -1152,7 +1165,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
} }
self->copyfile =NULL; self->copyfile =NULL;
return res; return res;
} }
@ -1171,7 +1184,7 @@ _psyco_curs_has_write_check(PyObject* o, void* var)
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"argument 1 must have a .write() method"); "argument 1 must have a .write() method");
return 0; return 0;
} }
} }
static PyObject * static PyObject *
@ -1189,7 +1202,7 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
&table_name, &sep, &null)) { &table_name, &sep, &null)) {
return NULL; return NULL;
} }
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
if (null) { if (null) {
@ -1206,13 +1219,13 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
if (pq_execute(self, query, 0) == 1) { if (pq_execute(self, query, 0) == 1) {
res = Py_None; res = Py_None;
Py_INCREF(Py_None); Py_INCREF(Py_None);
} }
self->copyfile = NULL; self->copyfile = NULL;
return res; return res;
} }
/* extension: fileno - return the file descripor of the connection */ /* extension: fileno - return the file descripor of the connection */
#define psyco_curs_fileno_doc \ #define psyco_curs_fileno_doc \
@ -1222,7 +1235,7 @@ static PyObject *
psyco_curs_fileno(cursorObject *self, PyObject *args) psyco_curs_fileno(cursorObject *self, PyObject *args)
{ {
long int socket; long int socket;
if (!PyArg_ParseTuple(args, "")) return NULL; if (!PyArg_ParseTuple(args, "")) return NULL;
EXC_IF_CURS_CLOSED(self); EXC_IF_CURS_CLOSED(self);
@ -1252,7 +1265,7 @@ psyco_curs_isready(cursorObject *self, PyObject *args)
/* pq_is_busy does its own locking, we don't need anything special but if /* pq_is_busy does its own locking, we don't need anything special but if
the cursor is ready we need to fetch the result and free the connection the cursor is ready we need to fetch the result and free the connection
for the next query. */ for the next query. */
if (pq_is_busy(self->conn)) { if (pq_is_busy(self->conn)) {
Py_INCREF(Py_False); Py_INCREF(Py_False);
return Py_False; return Py_False;
@ -1351,7 +1364,7 @@ static struct PyMemberDef cursorObject_members[] = {
/* DBAPI-2.0 basics */ /* DBAPI-2.0 basics */
{"rowcount", T_LONG, OFFSETOF(rowcount), RO, {"rowcount", T_LONG, OFFSETOF(rowcount), RO,
"Number of rows read from the backend in the last command."}, "Number of rows read from the backend in the last command."},
{"arraysize", T_LONG, OFFSETOF(arraysize), 0, {"arraysize", T_LONG, OFFSETOF(arraysize), 0,
"Number of records `fetchmany()` must fetch if not explicitely " \ "Number of records `fetchmany()` must fetch if not explicitely " \
"specified."}, "specified."},
{"description", T_OBJECT, OFFSETOF(description), RO, {"description", T_OBJECT, OFFSETOF(description), RO,
@ -1361,7 +1374,7 @@ static struct PyMemberDef cursorObject_members[] = {
/* DBAPI-2.0 extensions */ /* DBAPI-2.0 extensions */
{"rownumber", T_LONG, OFFSETOF(row), RO, {"rownumber", T_LONG, OFFSETOF(row), RO,
"The current row position."}, "The current row position."},
{"connection", T_OBJECT, OFFSETOF(conn), RO, {"connection", T_OBJECT, OFFSETOF(conn), RO,
"The connection where the cursor comes from."}, "The connection where the cursor comes from."},
#ifdef PSYCOPG_EXTENSIONS #ifdef PSYCOPG_EXTENSIONS
{"name", T_STRING, OFFSETOF(name), RO}, {"name", T_STRING, OFFSETOF(name), RO},
@ -1385,7 +1398,7 @@ cursor_setup(cursorObject *self, connectionObject *conn, char *name)
{ {
Dprintf("cursor_setup: init cursor object at %p", self); Dprintf("cursor_setup: init cursor object at %p", self);
Dprintf("cursor_setup: parameters: name = %s, conn = %p", name, conn); Dprintf("cursor_setup: parameters: name = %s, conn = %p", name, conn);
if (name) { if (name) {
self->name = PyMem_Malloc(strlen(name)+1); self->name = PyMem_Malloc(strlen(name)+1);
if (self->name == NULL) return 1; if (self->name == NULL) return 1;
@ -1401,21 +1414,21 @@ cursor_setup(cursorObject *self, connectionObject *conn, char *name)
} */ } */
self->conn = conn; self->conn = conn;
Py_INCREF((PyObject*)self->conn); Py_INCREF((PyObject*)self->conn);
self->closed = 0; self->closed = 0;
self->mark = conn->mark; self->mark = conn->mark;
self->pgres = NULL; self->pgres = NULL;
self->notuples = 1; self->notuples = 1;
self->arraysize = 1; self->arraysize = 1;
self->rowcount = -1; self->rowcount = -1;
self->lastoid = InvalidOid; self->lastoid = InvalidOid;
self->casts = NULL; self->casts = NULL;
self->notice = NULL; self->notice = NULL;
self->string_types = NULL; self->string_types = NULL;
self->binary_types = NULL; self->binary_types = NULL;
self->description = Py_None; self->description = Py_None;
Py_INCREF(Py_None); Py_INCREF(Py_None);
self->pgstatus = Py_None; self->pgstatus = Py_None;
@ -1424,13 +1437,15 @@ cursor_setup(cursorObject *self, connectionObject *conn, char *name)
Py_INCREF(Py_None); Py_INCREF(Py_None);
self->query = Py_None; self->query = Py_None;
Py_INCREF(Py_None); Py_INCREF(Py_None);
/* default tzinfo factory */ /* default tzinfo factory */
self->tzinfo_factory = pyPsycopgTzFixedOffsetTimezone; self->tzinfo_factory = pyPsycopgTzFixedOffsetTimezone;
Py_INCREF(self->tzinfo_factory); Py_INCREF(self->tzinfo_factory);
Dprintf("cursor_setup: good cursor object at %p, refcnt = %d", Dprintf("cursor_setup: good cursor object at %p, refcnt = "
self, ((PyObject *)self)->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
self, ((PyObject *)self)->ob_refcnt
);
return 0; return 0;
} }
@ -1440,7 +1455,7 @@ cursor_dealloc(PyObject* obj)
cursorObject *self = (cursorObject *)obj; cursorObject *self = (cursorObject *)obj;
if (self->name) PyMem_Free(self->name); if (self->name) PyMem_Free(self->name);
Py_XDECREF((PyObject*)self->conn); Py_XDECREF((PyObject*)self->conn);
Py_XDECREF(self->casts); Py_XDECREF(self->casts);
Py_XDECREF(self->description); Py_XDECREF(self->description);
@ -1450,11 +1465,13 @@ cursor_dealloc(PyObject* obj)
Py_XDECREF(self->query); Py_XDECREF(self->query);
Py_XDECREF(self->string_types); Py_XDECREF(self->string_types);
Py_XDECREF(self->binary_types); Py_XDECREF(self->binary_types);
IFCLEARPGRES(self->pgres); IFCLEARPGRES(self->pgres);
Dprintf("cursor_dealloc: deleted cursor object at %p, refcnt = %d", Dprintf("cursor_dealloc: deleted cursor object at %p, refcnt = "
obj, obj->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
obj, obj->ob_refcnt
);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -1464,7 +1481,7 @@ cursor_init(PyObject *obj, PyObject *args, PyObject *kwds)
{ {
char *name = NULL; char *name = NULL;
PyObject *conn; PyObject *conn;
if (!PyArg_ParseTuple(args, "O|s", &conn, &name)) if (!PyArg_ParseTuple(args, "O|s", &conn, &name))
return -1; return -1;
@ -1503,7 +1520,7 @@ PyTypeObject cursorType = {
sizeof(cursorObject), sizeof(cursorObject),
0, 0,
cursor_dealloc, /*tp_dealloc*/ cursor_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
@ -1521,7 +1538,7 @@ PyTypeObject cursorType = {
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
cursorType_doc, /*tp_doc*/ cursorType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -1538,11 +1555,11 @@ PyTypeObject cursorType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
cursor_init, /*tp_init*/ cursor_init, /*tp_init*/
0, /*tp_alloc Will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc Will be set to PyType_GenericAlloc in module init*/
cursor_new, /*tp_new*/ cursor_new, /*tp_new*/

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
@ -44,10 +45,10 @@ microprotocols_init(PyObject *dict)
/* create adapters dictionary and put it in module namespace */ /* create adapters dictionary and put it in module namespace */
if ((psyco_adapters = PyDict_New()) == NULL) { if ((psyco_adapters = PyDict_New()) == NULL) {
return -1; return -1;
} }
PyDict_SetItemString(dict, "adapters", psyco_adapters); PyDict_SetItemString(dict, "adapters", psyco_adapters);
return 0; return 0;
} }
@ -79,7 +80,7 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
quotable object to be its instance */ quotable object to be its instance */
Dprintf("microprotocols_adapt: trying to adapt %s", obj->ob_type->tp_name); Dprintf("microprotocols_adapt: trying to adapt %s", obj->ob_type->tp_name);
/* look for an adapter in the registry */ /* look for an adapter in the registry */
key = Py_BuildValue("(OO)", (PyObject*)obj->ob_type, proto); key = Py_BuildValue("(OO)", (PyObject*)obj->ob_type, proto);
adapter = PyDict_GetItem(psyco_adapters, key); adapter = PyDict_GetItem(psyco_adapters, key);
@ -98,7 +99,7 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
return NULL; return NULL;
} }
/* and finally try to have the object adapt itself */ /* and finally try to have the object adapt itself */
if (PyObject_HasAttrString(obj, "__conform__")) { if (PyObject_HasAttrString(obj, "__conform__")) {
PyObject *adapted = PyObject_CallMethod(obj, "__conform__","O", proto); PyObject *adapted = PyObject_CallMethod(obj, "__conform__","O", proto);
if (adapted && adapted != Py_None) return adapted; if (adapted && adapted != Py_None) return adapted;
@ -106,7 +107,7 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError))
return NULL; return NULL;
} }
/* else set the right exception and return NULL */ /* else set the right exception and return NULL */
psyco_set_error(ProgrammingError, NULL, "can't adapt", NULL, NULL); psyco_set_error(ProgrammingError, NULL, "can't adapt", NULL, NULL);
return NULL; return NULL;
@ -120,7 +121,7 @@ microprotocol_getquoted(PyObject *obj, connectionObject *conn)
PyObject *res = NULL; PyObject *res = NULL;
PyObject *tmp = microprotocols_adapt( PyObject *tmp = microprotocols_adapt(
obj, (PyObject*)&isqlquoteType, NULL); obj, (PyObject*)&isqlquoteType, NULL);
if (tmp != NULL) { if (tmp != NULL) {
Dprintf("microprotocol_getquoted: adapted to %s", Dprintf("microprotocol_getquoted: adapted to %s",
tmp->ob_type->tp_name); tmp->ob_type->tp_name);

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_MICROPROTOCOLS_H #ifndef PSYCOPG_MICROPROTOCOLS_H
#define PSYCOPG_MICROPROTOCOLS_H 1 #define PSYCOPG_MICROPROTOCOLS_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include "psycopg/connection.h" #include "psycopg/connection.h"
#include "psycopg/cursor.h" #include "psycopg/cursor.h"
@ -46,15 +47,15 @@ extern PyObject *psyco_adapters;
extern int microprotocols_init(PyObject *dict); extern int microprotocols_init(PyObject *dict);
extern int microprotocols_add( extern int microprotocols_add(
PyTypeObject *type, PyObject *proto, PyObject *cast); PyTypeObject *type, PyObject *proto, PyObject *cast);
extern PyObject *microprotocols_adapt( extern PyObject *microprotocols_adapt(
PyObject *obj, PyObject *proto, PyObject *alt); PyObject *obj, PyObject *proto, PyObject *alt);
extern PyObject *microprotocol_getquoted( extern PyObject *microprotocol_getquoted(
PyObject *obj, connectionObject *conn); PyObject *obj, connectionObject *conn);
extern PyObject * extern PyObject *
psyco_microprotocols_adapt(cursorObject *self, PyObject *args); psyco_microprotocols_adapt(cursorObject *self, PyObject *args);
#define psyco_microprotocols_adapt_doc \ #define psyco_microprotocols_adapt_doc \
"adapt(obj, protocol, alternate) -> object -- adapt obj to given protocol" "adapt(obj, protocol, alternate) -> object -- adapt obj to given protocol"
#endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
#include <stringobject.h> #include <stringobject.h>
@ -44,7 +45,7 @@ static PyObject *
psyco_isqlquote_getquoted(isqlquoteObject *self, PyObject *args) psyco_isqlquote_getquoted(isqlquoteObject *self, PyObject *args)
{ {
if (!PyArg_ParseTuple(args, "")) return NULL; if (!PyArg_ParseTuple(args, "")) return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
@ -58,7 +59,7 @@ static PyObject *
psyco_isqlquote_getbinary(isqlquoteObject *self, PyObject *args) psyco_isqlquote_getbinary(isqlquoteObject *self, PyObject *args)
{ {
if (!PyArg_ParseTuple(args, "")) return NULL; if (!PyArg_ParseTuple(args, "")) return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
@ -72,7 +73,7 @@ static PyObject *
psyco_isqlquote_getbuffer(isqlquoteObject *self, PyObject *args) psyco_isqlquote_getbuffer(isqlquoteObject *self, PyObject *args)
{ {
if (!PyArg_ParseTuple(args, "")) return NULL; if (!PyArg_ParseTuple(args, "")) return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
@ -119,9 +120,9 @@ static void
isqlquote_dealloc(PyObject* obj) isqlquote_dealloc(PyObject* obj)
{ {
isqlquoteObject *self = (isqlquoteObject *)obj; isqlquoteObject *self = (isqlquoteObject *)obj;
Py_XDECREF(self->wrapped); Py_XDECREF(self->wrapped);
obj->ob_type->tp_free(obj); obj->ob_type->tp_free(obj);
} }
@ -163,7 +164,7 @@ PyTypeObject isqlquoteType = {
sizeof(isqlquoteObject), sizeof(isqlquoteObject),
0, 0,
isqlquote_dealloc, /*tp_dealloc*/ isqlquote_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
0, /*tp_compare*/ 0, /*tp_compare*/
@ -181,7 +182,7 @@ PyTypeObject isqlquoteType = {
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
isqlquoteType_doc, /*tp_doc*/ isqlquoteType_doc, /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -198,11 +199,11 @@ PyTypeObject isqlquoteType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
isqlquote_init, /*tp_init*/ isqlquote_init, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
isqlquote_new, /*tp_new*/ isqlquote_new, /*tp_new*/

View File

@ -22,22 +22,23 @@
#ifndef PSYCOPG_ISQLQUOTE_H #ifndef PSYCOPG_ISQLQUOTE_H
#define PSYCOPG_ISQLQUOTE_H 1 #define PSYCOPG_ISQLQUOTE_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <libpq-fe.h> #include <libpq-fe.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern PyTypeObject isqlquoteType; extern PyTypeObject isqlquoteType;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *wrapped; PyObject *wrapped;
} isqlquoteObject; } isqlquoteObject;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -25,6 +25,7 @@
connection. connection.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <string.h> #include <string.h>
@ -47,17 +48,17 @@ void
pq_raise(connectionObject *conn, cursorObject *curs, PyObject *exc, char *msg) pq_raise(connectionObject *conn, cursorObject *curs, PyObject *exc, char *msg)
{ {
PyObject *pgc = (PyObject*)curs; PyObject *pgc = (PyObject*)curs;
char *err = NULL; char *err = NULL;
char *err2 = NULL; char *err2 = NULL;
char *code = NULL; char *code = NULL;
char *buf = NULL; char *buf = NULL;
if ((conn == NULL && curs == NULL) || (curs != NULL && conn == NULL)) { if ((conn == NULL && curs == NULL) || (curs != NULL && conn == NULL)) {
PyErr_SetString(Error, "psycopg went psycotic and raised a null error"); PyErr_SetString(Error, "psycopg went psycotic and raised a null error");
return; return;
} }
if (curs && curs->pgres) { if (curs && curs->pgres) {
err = PQresultErrorMessage(curs->pgres); err = PQresultErrorMessage(curs->pgres);
#ifdef HAVE_PQPROTOCOL3 #ifdef HAVE_PQPROTOCOL3
@ -76,7 +77,7 @@ pq_raise(connectionObject *conn, cursorObject *curs, PyObject *exc, char *msg)
PyErr_SetString(Error, "psycopg went psycotic without error set"); PyErr_SetString(Error, "psycopg went psycotic without error set");
return; return;
} }
/* if exc is NULL, analyze the message and try to deduce the right /* if exc is NULL, analyze the message and try to deduce the right
exception kind (only if we have a pgres, obviously) */ exception kind (only if we have a pgres, obviously) */
if (exc == NULL) { if (exc == NULL) {
@ -93,7 +94,7 @@ pq_raise(connectionObject *conn, cursorObject *curs, PyObject *exc, char *msg)
} }
} }
} }
/* if exc is still NULL psycopg was not built with HAVE_PQPROTOCOL3 or the /* if exc is still NULL psycopg was not built with HAVE_PQPROTOCOL3 or the
connection is using protocol 2: in both cases we default to comparing connection is using protocol 2: in both cases we default to comparing
error messages */ error messages */
@ -105,7 +106,7 @@ pq_raise(connectionObject *conn, cursorObject *curs, PyObject *exc, char *msg)
else else
exc = ProgrammingError; exc = ProgrammingError;
} }
/* try to remove the initial "ERROR: " part from the postgresql error */ /* try to remove the initial "ERROR: " part from the postgresql error */
if (err && strlen(err) > 8) err2 = &(err[8]); if (err && strlen(err) > 8) err2 = &(err[8]);
else err2 = err; else err2 = err;
@ -126,9 +127,9 @@ pq_raise(connectionObject *conn, cursorObject *curs, PyObject *exc, char *msg)
} }
} }
else { else {
psyco_set_error(exc, pgc, err2, err, code); psyco_set_error(exc, pgc, err2, err, code);
} }
if (buf != NULL) PyMem_Free(buf); if (buf != NULL) PyMem_Free(buf);
} }
@ -144,7 +145,7 @@ pq_raise(connectionObject *conn, cursorObject *curs, PyObject *exc, char *msg)
void void
pq_set_critical(connectionObject *conn, const char *msg) pq_set_critical(connectionObject *conn, const char *msg)
{ {
if (msg == NULL) if (msg == NULL)
msg = PQerrorMessage(conn->pgconn); msg = PQerrorMessage(conn->pgconn);
if (conn->critical) free(conn->critical); if (conn->critical) free(conn->critical);
if (msg && msg[0] != '\0') conn->critical = strdup(msg); if (msg && msg[0] != '\0') conn->critical = strdup(msg);
@ -155,7 +156,7 @@ PyObject *
pq_resolve_critical(connectionObject *conn, int close) pq_resolve_critical(connectionObject *conn, int close)
{ {
Dprintf("pq_resolve_critical: resolving %s", conn->critical); Dprintf("pq_resolve_critical: resolving %s", conn->critical);
if (conn->critical) { if (conn->critical) {
char *msg = &(conn->critical[6]); char *msg = &(conn->critical[6]);
Dprintf("pq_resolve_critical: error = %s", msg); Dprintf("pq_resolve_critical: error = %s", msg);
@ -163,7 +164,7 @@ pq_resolve_critical(connectionObject *conn, int close)
from the connection, so we just raise an OperationalError with the from the connection, so we just raise an OperationalError with the
critical message */ critical message */
PyErr_SetString(OperationalError, msg); PyErr_SetString(OperationalError, msg);
/* we don't want to destroy this connection but just close it */ /* we don't want to destroy this connection but just close it */
if (close == 1) conn_close(conn); if (close == 1) conn_close(conn);
} }
@ -175,7 +176,7 @@ pq_resolve_critical(connectionObject *conn, int close)
note that this function does block because it needs to wait for the full note that this function does block because it needs to wait for the full
result sets of the previous query to clear them. result sets of the previous query to clear them.
this function does not call any Py_*_ALLOW_THREADS macros */ this function does not call any Py_*_ALLOW_THREADS macros */
void void
@ -201,7 +202,7 @@ pq_begin(connectionObject *conn)
NULL, NULL,
"BEGIN; SET TRANSACTION ISOLATION LEVEL READ COMMITTED", "BEGIN; SET TRANSACTION ISOLATION LEVEL READ COMMITTED",
"BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"}; "BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"};
int pgstatus, retvalue = -1; int pgstatus, retvalue = -1;
PGresult *pgres = NULL; PGresult *pgres = NULL;
@ -324,7 +325,7 @@ pq_abort(connectionObject *conn)
} }
/* pq_is_busy - consume input and return connection status /* pq_is_busy - consume input and return connection status
a status of 1 means that a call to pq_fetch will block, while a status of 0 a status of 1 means that a call to pq_fetch will block, while a status of 0
means that there is data available to be collected. -1 means an error, the means that there is data available to be collected. -1 means an error, the
exception will be set accordingly. exception will be set accordingly.
@ -336,7 +337,7 @@ int
pq_is_busy(connectionObject *conn) pq_is_busy(connectionObject *conn)
{ {
PGnotify *pgn; PGnotify *pgn;
Dprintf("pq_is_busy: consuming input"); Dprintf("pq_is_busy: consuming input");
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
@ -352,13 +353,13 @@ pq_is_busy(connectionObject *conn)
pthread_mutex_unlock(&(conn->lock)); pthread_mutex_unlock(&(conn->lock));
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
/* now check for notifies */ /* now check for notifies */
while ((pgn = PQnotifies(conn->pgconn)) != NULL) { while ((pgn = PQnotifies(conn->pgconn)) != NULL) {
PyObject *notify; PyObject *notify;
Dprintf("curs_is_busy: got NOTIFY from pid %d, msg = %s", Dprintf("curs_is_busy: got NOTIFY from pid %d, msg = %s",
pgn->be_pid, pgn->relname); (int) pgn->be_pid, pgn->relname);
notify = PyTuple_New(2); notify = PyTuple_New(2);
PyTuple_SET_ITEM(notify, 0, PyInt_FromLong((long)pgn->be_pid)); PyTuple_SET_ITEM(notify, 0, PyInt_FromLong((long)pgn->be_pid));
@ -366,7 +367,7 @@ pq_is_busy(connectionObject *conn)
PyList_Append(conn->notifies, notify); PyList_Append(conn->notifies, notify);
free(pgn); free(pgn);
} }
return PQisBusy(conn->pgconn); return PQisBusy(conn->pgconn);
} }
@ -410,10 +411,10 @@ pq_execute(cursorObject *curs, const char *query, int async)
not what should we do? just block and discard data or execute not what should we do? just block and discard data or execute
another query? */ another query? */
pq_clear_async(curs->conn); pq_clear_async(curs->conn);
Dprintf("pq_execute: executing ASYNC query:"); Dprintf("pq_execute: executing ASYNC query:");
Dprintf(" %-.200s", query); Dprintf(" %-.200s", query);
/* then we can go on and send a new query without fear */ /* then we can go on and send a new query without fear */
IFCLEARPGRES(curs->pgres); IFCLEARPGRES(curs->pgres);
if (PQsendQuery(curs->conn->pgconn, query) == 0) { if (PQsendQuery(curs->conn->pgconn, query) == 0) {
@ -425,10 +426,10 @@ pq_execute(cursorObject *curs, const char *query, int async)
} }
Dprintf("pq_execute: async query sent to backend"); Dprintf("pq_execute: async query sent to backend");
} }
pthread_mutex_unlock(&(curs->conn->lock)); pthread_mutex_unlock(&(curs->conn->lock));
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
/* if the execute was sync, we call pq_fetch() immediately, /* if the execute was sync, we call pq_fetch() immediately,
to respect the old DBAPI-2.0 compatible behaviour */ to respect the old DBAPI-2.0 compatible behaviour */
if (async == 0) { if (async == 0) {
@ -438,7 +439,7 @@ pq_execute(cursorObject *curs, const char *query, int async)
else { else {
curs->conn->async_cursor = (PyObject*)curs; curs->conn->async_cursor = (PyObject*)curs;
} }
return 1-async; return 1-async;
} }
@ -470,7 +471,7 @@ _pq_fetch_tuples(cursorObject *curs)
curs->description = PyTuple_New(pgnfields); curs->description = PyTuple_New(pgnfields);
curs->casts = PyTuple_New(pgnfields); curs->casts = PyTuple_New(pgnfields);
curs->columns = pgnfields; curs->columns = pgnfields;
/* calculate the display size for each column (cpu intensive, can be /* calculate the display size for each column (cpu intensive, can be
switched off at configuration time) */ switched off at configuration time) */
#ifdef PSYCOPG_DISPLAY_SIZE #ifdef PSYCOPG_DISPLAY_SIZE
@ -494,13 +495,13 @@ _pq_fetch_tuples(cursorObject *curs)
Oid ftype = PQftype(curs->pgres, i); Oid ftype = PQftype(curs->pgres, i);
int fsize = PQfsize(curs->pgres, i); int fsize = PQfsize(curs->pgres, i);
int fmod = PQfmod(curs->pgres, i); int fmod = PQfmod(curs->pgres, i);
PyObject *dtitem = PyTuple_New(7); PyObject *dtitem = PyTuple_New(7);
PyObject *type = PyInt_FromLong(ftype); PyObject *type = PyInt_FromLong(ftype);
PyObject *cast = NULL; PyObject *cast = NULL;
PyTuple_SET_ITEM(curs->description, i, dtitem); PyTuple_SET_ITEM(curs->description, i, dtitem);
/* fill the right cast function by accessing three different dictionaries: /* fill the right cast function by accessing three different dictionaries:
- the per-cursor dictionary, if available (can be NULL or None) - the per-cursor dictionary, if available (can be NULL or None)
- the per-connection dictionary (always exists but can be null) - the per-connection dictionary (always exists but can be null)
@ -521,7 +522,7 @@ _pq_fetch_tuples(cursorObject *curs)
Dprintf("_pq_fetch_tuples: global dict: %p", cast); Dprintf("_pq_fetch_tuples: global dict: %p", cast);
} }
if (cast == NULL) cast = psyco_default_cast; if (cast == NULL) cast = psyco_default_cast;
/* else if we got binary tuples and if we got a field that /* else if we got binary tuples and if we got a field that
is binary use the default cast is binary use the default cast
FIXME: what the hell am I trying to do here? This just can't work.. FIXME: what the hell am I trying to do here? This just can't work..
@ -538,7 +539,7 @@ _pq_fetch_tuples(cursorObject *curs)
PQftype(curs->pgres,i)); PQftype(curs->pgres,i));
Py_INCREF(cast); Py_INCREF(cast);
PyTuple_SET_ITEM(curs->casts, i, cast); PyTuple_SET_ITEM(curs->casts, i, cast);
/* 1/ fill the other fields */ /* 1/ fill the other fields */
PyTuple_SET_ITEM(dtitem, 0, PyTuple_SET_ITEM(dtitem, 0,
PyString_FromString(PQfname(curs->pgres, i))); PyString_FromString(PQfname(curs->pgres, i)));
@ -584,7 +585,7 @@ _pq_fetch_tuples(cursorObject *curs)
Py_INCREF(Py_None); Py_INCREF(Py_None);
PyTuple_SET_ITEM(dtitem, 6, Py_None); PyTuple_SET_ITEM(dtitem, 6, Py_None);
} }
if (dsize) PyMem_Free(dsize); if (dsize) PyMem_Free(dsize);
} }
@ -598,14 +599,16 @@ _pq_copy_in_v3(cursorObject *curs)
PyObject *o; PyObject *o;
Py_ssize_t length = 0; Py_ssize_t length = 0;
int error = 0; int error = 0;
while (1) { while (1) {
o = PyObject_CallMethod(curs->copyfile, "read", "i", curs->copysize); o = PyObject_CallMethod(curs->copyfile, "read",
CONV_CODE_PY_SSIZE_T, curs->copysize
);
if (!o || !PyString_Check(o) || (length = PyString_Size(o)) == -1) { if (!o || !PyString_Check(o) || (length = PyString_Size(o)) == -1) {
error = 1; error = 1;
} }
if (length == 0 || error == 1) break; if (length == 0 || error == 1) break;
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
if (PQputCopyData(curs->conn->pgconn, if (PQputCopyData(curs->conn->pgconn,
PyString_AS_STRING(o), length) == -1) { PyString_AS_STRING(o), length) == -1) {
@ -614,12 +617,12 @@ _pq_copy_in_v3(cursorObject *curs)
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
if (error == 2) break; if (error == 2) break;
Py_DECREF(o); Py_DECREF(o);
} }
Py_XDECREF(o); Py_XDECREF(o);
Dprintf("_pq_copy_in_v3: error = %d", error); Dprintf("_pq_copy_in_v3: error = %d", error);
if (error == 0 || error == 2) if (error == 0 || error == 2)
@ -682,13 +685,13 @@ _pq_copy_out_v3(cursorObject *curs)
PyObject *tmp = NULL; PyObject *tmp = NULL;
char *buffer; char *buffer;
int len; Py_ssize_t len;
while (1) { while (1) {
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
len = PQgetCopyData(curs->conn->pgconn, &buffer, 0); len = PQgetCopyData(curs->conn->pgconn, &buffer, 0);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
if (len > 0 && buffer) { if (len > 0 && buffer) {
tmp = PyObject_CallMethod(curs->copyfile, tmp = PyObject_CallMethod(curs->copyfile,
"write", "s#", buffer, len); "write", "s#", buffer, len);
@ -703,7 +706,7 @@ _pq_copy_out_v3(cursorObject *curs)
postgresql authors :/) */ postgresql authors :/) */
else if (len <= 0) break; else if (len <= 0) break;
} }
if (len == -2) { if (len == -2) {
pq_raise(curs->conn, NULL, NULL, NULL); pq_raise(curs->conn, NULL, NULL, NULL);
return -1; return -1;
@ -726,8 +729,9 @@ _pq_copy_out(cursorObject *curs)
PyObject *tmp = NULL; PyObject *tmp = NULL;
char buffer[4096]; char buffer[4096];
int status, len, ll=0; int status, ll=0;
Py_ssize_t len;
while (1) { while (1) {
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
status = PQgetline(curs->conn->pgconn, buffer, 4096); status = PQgetline(curs->conn->pgconn, buffer, 4096);
@ -735,7 +739,7 @@ _pq_copy_out(cursorObject *curs)
if (status == 0) { if (status == 0) {
if (!ll && buffer[0] == '\\' && buffer[1] == '.') break; if (!ll && buffer[0] == '\\' && buffer[1] == '.') break;
len = strlen(buffer); len = (Py_ssize_t) strlen(buffer);
buffer[len++] = '\n'; buffer[len++] = '\n';
ll = 0; ll = 0;
} }
@ -746,7 +750,7 @@ _pq_copy_out(cursorObject *curs)
else { else {
return -1; return -1;
} }
tmp = PyObject_CallMethod(curs->copyfile, "write", "s#", buffer, len); tmp = PyObject_CallMethod(curs->copyfile, "write", "s#", buffer, len);
if (tmp == NULL) if (tmp == NULL)
return -1; return -1;
@ -757,7 +761,7 @@ _pq_copy_out(cursorObject *curs)
status = 1; status = 1;
if (PQendcopy(curs->conn->pgconn) != 0) if (PQendcopy(curs->conn->pgconn) != 0)
status = -1; status = -1;
/* if for some reason we're using a protocol 3 libpq to connect to a /* if for some reason we're using a protocol 3 libpq to connect to a
protocol 2 backend we still need to cycle on the result set */ protocol 2 backend we still need to cycle on the result set */
IFCLEARPGRES(curs->pgres); IFCLEARPGRES(curs->pgres);
@ -777,14 +781,14 @@ pq_fetch(cursorObject *curs)
/* even if we fail, we remove any information about the previous query */ /* even if we fail, we remove any information about the previous query */
curs_reset(curs); curs_reset(curs);
/* we check the result from the previous execute; if the result is not /* we check the result from the previous execute; if the result is not
already there, we need to consume some input and go to sleep until we already there, we need to consume some input and go to sleep until we
get something edible to eat */ get something edible to eat */
if (!curs->pgres) { if (!curs->pgres) {
Dprintf("pq_fetch: no data: entering polling loop"); Dprintf("pq_fetch: no data: entering polling loop");
while (pq_is_busy(curs->conn) > 0) { while (pq_is_busy(curs->conn) > 0) {
fd_set rfds; fd_set rfds;
struct timeval tv; struct timeval tv;
@ -830,9 +834,9 @@ pq_fetch(cursorObject *curs)
} }
} }
*/ */
if (curs->pgres == NULL) return 0; if (curs->pgres == NULL) return 0;
pgstatus = PQresultStatus(curs->pgres); pgstatus = PQresultStatus(curs->pgres);
Dprintf("pq_fetch: pgstatus = %s", PQresStatus(pgstatus)); Dprintf("pq_fetch: pgstatus = %s", PQresStatus(pgstatus));
@ -863,11 +867,11 @@ pq_fetch(cursorObject *curs)
if (PyErr_Occurred()) ex = -1; if (PyErr_Occurred()) ex = -1;
IFCLEARPGRES(curs->pgres); IFCLEARPGRES(curs->pgres);
break; break;
case PGRES_COPY_IN: case PGRES_COPY_IN:
Dprintf("pq_fetch: data from a COPY FROM (no tuples)"); Dprintf("pq_fetch: data from a COPY FROM (no tuples)");
#ifdef HAVE_PQPROTOCOL3 #ifdef HAVE_PQPROTOCOL3
if (curs->conn->protocol == 3) if (curs->conn->protocol == 3)
ex = _pq_copy_in_v3(curs); ex = _pq_copy_in_v3(curs);
else else
#endif #endif
@ -877,14 +881,14 @@ pq_fetch(cursorObject *curs)
if (PyErr_Occurred()) ex = -1; if (PyErr_Occurred()) ex = -1;
IFCLEARPGRES(curs->pgres); IFCLEARPGRES(curs->pgres);
break; break;
case PGRES_TUPLES_OK: case PGRES_TUPLES_OK:
Dprintf("pq_fetch: data from a SELECT (got tuples)"); Dprintf("pq_fetch: data from a SELECT (got tuples)");
curs->rowcount = PQntuples(curs->pgres); curs->rowcount = PQntuples(curs->pgres);
_pq_fetch_tuples(curs); ex = 0; _pq_fetch_tuples(curs); ex = 0;
/* don't clear curs->pgres, because it contains the results! */ /* don't clear curs->pgres, because it contains the results! */
break; break;
default: default:
Dprintf("pq_fetch: uh-oh, something FAILED"); Dprintf("pq_fetch: uh-oh, something FAILED");
pq_raise(curs->conn, curs, NULL, NULL); pq_raise(curs->conn, curs, NULL, NULL);
@ -894,7 +898,7 @@ pq_fetch(cursorObject *curs)
} }
Dprintf("pq_fetch: fetching done; check for critical errors"); Dprintf("pq_fetch: fetching done; check for critical errors");
/* error checking, close the connection if necessary (some critical errors /* error checking, close the connection if necessary (some critical errors
are not really critical, like a COPY FROM error: if that's the case we are not really critical, like a COPY FROM error: if that's the case we
raise the exception but we avoid to close the connection) */ raise the exception but we avoid to close the connection) */
@ -907,6 +911,6 @@ pq_fetch(cursorObject *curs)
} }
return -1; return -1;
} }
return ex; return ex;
} }

View File

@ -1,4 +1,4 @@
/* psycopg.h - definitions for the psycopg python module /* psycopg.h - definitions for the psycopg python module
* *
* Copyright (C) 2003 Federico Di Gregorio <fog@debian.org> * Copyright (C) 2003 Federico Di Gregorio <fog@debian.org>
* *
@ -22,35 +22,60 @@
#ifndef PSYCOPG_H #ifndef PSYCOPG_H
#define PSYCOPG_H 1 #define PSYCOPG_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Python 2.5 ssize_t compatibility */ /* Python 2.5+ Py_ssize_t compatibility: */
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) #ifndef PY_FORMAT_SIZE_T
typedef int Py_ssize_t; #define PY_FORMAT_SIZE_T ""
#define PY_SSIZE_T_MAX INT_MAX #endif
#define PY_SSIZE_T_MIN INT_MIN
/* FORMAT_CODE_SIZE_T is for plain size_t, not for Py_ssize_t: */
#ifdef _MSC_VER
/* For MSVC: */
#define FORMAT_CODE_SIZE_T "%Iu"
#else
/* C99 standard format code: */
#define FORMAT_CODE_SIZE_T "%zu"
#endif
/* FORMAT_CODE_PY_SSIZE_T is for Py_ssize_t: */
#define FORMAT_CODE_PY_SSIZE_T "%" PY_FORMAT_SIZE_T "d"
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 5
#define CONV_CODE_PY_SSIZE_T "n"
#else
#define CONV_CODE_PY_SSIZE_T "d"
typedef int Py_ssize_t;
#define PY_SSIZE_T_MIN INT_MIN
#define PY_SSIZE_T_MAX INT_MAX
#define readbufferproc getreadbufferproc
#define writebufferproc getwritebufferproc
#define segcountproc getsegcountproc
#define charbufferproc getcharbufferproc
#endif #endif
/* DBAPI compliance parameters */ /* DBAPI compliance parameters */
#define APILEVEL "2.0" #define APILEVEL "2.0"
#define THREADSAFETY 2 #define THREADSAFETY 2
#define PARAMSTYLE "pyformat" #define PARAMSTYLE "pyformat"
/* C API functions */ /* C API functions */
#define psyco_errors_fill_NUM 0 #define psyco_errors_fill_NUM 0
#define psyco_errors_fill_RETURN void #define psyco_errors_fill_RETURN void
#define psyco_errors_fill_PROTO (PyObject *dict) #define psyco_errors_fill_PROTO (PyObject *dict)
#define psyco_errors_set_NUM 1 #define psyco_errors_set_NUM 1
#define psyco_errors_set_RETURN void #define psyco_errors_set_RETURN void
#define psyco_errors_set_PROTO (PyObject *type) #define psyco_errors_set_PROTO (PyObject *type)
/* Total number of C API pointers */ /* Total number of C API pointers */
#define PSYCOPG_API_pointers 2 #define PSYCOPG_API_pointers 2
#ifdef PSYCOPG_MODULE #ifdef PSYCOPG_MODULE
/** This section is used when compiling psycopgmodule.c & co. **/ /** This section is used when compiling psycopgmodule.c & co. **/
extern psyco_errors_fill_RETURN psyco_errors_fill psyco_errors_fill_PROTO; extern psyco_errors_fill_RETURN psyco_errors_fill psyco_errors_fill_PROTO;
@ -65,7 +90,7 @@ extern PyObject *Error, *Warning, *InterfaceError, *DatabaseError,
#ifndef PyMODINIT_FUNC #ifndef PyMODINIT_FUNC
#define PyMODINIT_FUNC void #define PyMODINIT_FUNC void
#endif #endif
#else #else
/** This section is used in modules that use psycopg's C API **/ /** This section is used in modules that use psycopg's C API **/
@ -77,7 +102,7 @@ static void **PSYCOPG_API;
#define psyco_errors_set \ #define psyco_errors_set \
(*(psyco_errors_set_RETURN (*)psyco_errors_set_PROTO) \ (*(psyco_errors_set_RETURN (*)psyco_errors_set_PROTO) \
PSYCOPG_API[psyco_errors_set_NUM]) PSYCOPG_API[psyco_errors_set_NUM])
/* Return -1 and set exception on error, 0 on success. */ /* Return -1 and set exception on error, 0 on success. */
static int static int
import_psycopg(void) import_psycopg(void)
@ -98,19 +123,19 @@ import_psycopg(void)
/* postgresql<->python encoding map */ /* postgresql<->python encoding map */
extern PyObject *psycoEncodings; extern PyObject *psycoEncodings;
typedef struct { typedef struct {
char *pgenc; char *pgenc;
char *pyenc; char *pyenc;
} encodingPair; } encodingPair;
/* the Decimal type, used by the DECIMAL typecaster */ /* the Decimal type, used by the DECIMAL typecaster */
extern PyObject *decimalType; extern PyObject *decimalType;
/* some utility functions */ /* some utility functions */
extern void psyco_set_error(PyObject *exc, PyObject *curs, char *msg, extern void psyco_set_error(PyObject *exc, PyObject *curs, char *msg,
char *pgerror, char *pgcode); char *pgerror, char *pgcode);
/* Exceptions docstrings */ /* Exceptions docstrings */
#define Error_doc \ #define Error_doc \
"Base class for error exceptions." "Base class for error exceptions."

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#define PSYCOPG_MODULE #define PSYCOPG_MODULE
@ -127,16 +128,16 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
{ {
PyObject *conn, *factory = NULL; PyObject *conn, *factory = NULL;
PyObject *pyport = NULL; PyObject *pyport = NULL;
int idsn=-1, iport=-1; int idsn=-1, iport=-1;
char *dsn=NULL, *database=NULL, *user=NULL, *password=NULL; char *dsn=NULL, *database=NULL, *user=NULL, *password=NULL;
char *host=NULL, *sslmode=NULL; char *host=NULL, *sslmode=NULL;
char port[16]; char port[16];
static char *kwlist[] = {"dsn", "database", "host", "port", static char *kwlist[] = {"dsn", "database", "host", "port",
"user", "password", "sslmode", "user", "password", "sslmode",
"connection_factory", NULL}; "connection_factory", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sssOsssO", kwlist, if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sssOsssO", kwlist,
&dsn, &database, &host, &pyport, &dsn, &database, &host, &pyport,
&user, &password, &sslmode, &factory)) { &user, &password, &sslmode, &factory)) {
@ -144,16 +145,16 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
} }
if (pyport && PyString_Check(pyport)) { if (pyport && PyString_Check(pyport)) {
PyObject *pyint = PyInt_FromString(PyString_AsString(pyport), NULL, 10); PyObject *pyint = PyInt_FromString(PyString_AsString(pyport), NULL, 10);
if (!pyint) return NULL; if (!pyint) return NULL;
iport = PyInt_AsLong(pyint); iport = PyInt_AsLong(pyint);
} }
else if (pyport && PyInt_Check(pyport)) { else if (pyport && PyInt_Check(pyport)) {
iport = PyInt_AsLong(pyport); iport = PyInt_AsLong(pyport);
} }
else if (pyport != NULL) { else if (pyport != NULL) {
PyErr_SetString(PyExc_TypeError, "port must be a string or int"); PyErr_SetString(PyExc_TypeError, "port must be a string or int");
return NULL; return NULL;
} }
if (iport > 0) if (iport > 0)
@ -168,7 +169,7 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
if (user) l += strlen(user); if (user) l += strlen(user);
if (password) l += strlen(password); if (password) l += strlen(password);
if (sslmode) l += strlen(sslmode); if (sslmode) l += strlen(sslmode);
dsn = malloc(l*sizeof(char)); dsn = malloc(l*sizeof(char));
if (dsn == NULL) { if (dsn == NULL) {
PyErr_SetString(InterfaceError, "dynamic dsn allocation failed"); PyErr_SetString(InterfaceError, "dynamic dsn allocation failed");
@ -188,7 +189,7 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
idsn = _psyco_connect_fill_dsn(dsn, " password=", password, idsn); idsn = _psyco_connect_fill_dsn(dsn, " password=", password, idsn);
if (sslmode) if (sslmode)
idsn = _psyco_connect_fill_dsn(dsn, " sslmode=", sslmode, idsn); idsn = _psyco_connect_fill_dsn(dsn, " sslmode=", sslmode, idsn);
if (idsn > 0) { if (idsn > 0) {
dsn[idsn] = '\0'; dsn[idsn] = '\0';
memmove(dsn, &dsn[1], idsn); memmove(dsn, &dsn[1], idsn);
@ -206,7 +207,7 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
if (factory == NULL) factory = (PyObject *)&connectionType; if (factory == NULL) factory = (PyObject *)&connectionType;
conn = PyObject_CallFunction(factory, "s", dsn); conn = PyObject_CallFunction(factory, "s", dsn);
if (conn) _psyco_connect_fill_exc((connectionObject*)conn); if (conn) _psyco_connect_fill_exc((connectionObject*)conn);
return conn; return conn;
} }
@ -239,7 +240,7 @@ _psyco_register_type_set(PyObject **dict, PyObject *type)
static PyObject * static PyObject *
psyco_register_type(PyObject *self, PyObject *args) psyco_register_type(PyObject *self, PyObject *args)
{ {
PyObject *type, *obj; PyObject *type, *obj = NULL;
if (!PyArg_ParseTuple(args, "O!|O", &typecastType, &type, &obj)) { if (!PyArg_ParseTuple(args, "O!|O", &typecastType, &type, &obj)) {
return NULL; return NULL;
@ -273,16 +274,16 @@ static void
psyco_adapters_init(PyObject *mod) psyco_adapters_init(PyObject *mod)
{ {
PyObject *call; PyObject *call;
microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&asisType); microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&asisType);
microprotocols_add(&PyInt_Type, NULL, (PyObject*)&asisType); microprotocols_add(&PyInt_Type, NULL, (PyObject*)&asisType);
microprotocols_add(&PyLong_Type, NULL, (PyObject*)&asisType); microprotocols_add(&PyLong_Type, NULL, (PyObject*)&asisType);
microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType); microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType);
microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType); microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType);
microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType); microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType);
microprotocols_add(&PyList_Type, NULL, (PyObject*)&listType); microprotocols_add(&PyList_Type, NULL, (PyObject*)&listType);
#ifdef HAVE_MXDATETIME #ifdef HAVE_MXDATETIME
/* the module has already been initialized, so we can obtain the callable /* the module has already been initialized, so we can obtain the callable
objects directly from its dictionary :) */ objects directly from its dictionary :) */
@ -303,7 +304,7 @@ psyco_adapters_init(PyObject *mod)
call = PyMapping_GetItemString(mod, "IntervalFromPy"); call = PyMapping_GetItemString(mod, "IntervalFromPy");
microprotocols_add((PyTypeObject*)pyDeltaTypeP, NULL, call); microprotocols_add((PyTypeObject*)pyDeltaTypeP, NULL, call);
#endif #endif
#ifdef HAVE_PYBOOL #ifdef HAVE_PYBOOL
microprotocols_add(&PyBool_Type, NULL, (PyObject*)&pbooleanType); microprotocols_add(&PyBool_Type, NULL, (PyObject*)&pbooleanType);
#endif #endif
@ -314,19 +315,19 @@ psyco_adapters_init(PyObject *mod)
} }
/* psyco_encodings_fill /* psyco_encodings_fill
Fill the module's postgresql<->python encoding table */ Fill the module's postgresql<->python encoding table */
static encodingPair encodings[] = { static encodingPair encodings[] = {
{"SQL_ASCII", "ascii"}, {"SQL_ASCII", "ascii"},
{"LATIN1", "iso8859_1"}, {"LATIN1", "iso8859_1"},
{"LATIN2", "iso8859_2"}, {"LATIN2", "iso8859_2"},
{"LATIN3", "iso8859_3"}, {"LATIN3", "iso8859_3"},
{"LATIN4", "iso8859_4"}, {"LATIN4", "iso8859_4"},
{"LATIN5", "iso8859_9"}, {"LATIN5", "iso8859_9"},
{"LATIN6", "iso8859_10"}, {"LATIN6", "iso8859_10"},
{"LATIN7", "iso8859_13"}, {"LATIN7", "iso8859_13"},
{"LATIN8", "iso8859_14"}, {"LATIN8", "iso8859_14"},
{"LATIN9", "iso8859_15"}, {"LATIN9", "iso8859_15"},
{"ISO88591", "iso8859_1"}, {"ISO88591", "iso8859_1"},
{"ISO88592", "iso8859_2"}, {"ISO88592", "iso8859_2"},
@ -359,7 +360,7 @@ static encodingPair encodings[] = {
{"ShiftJIS", "cp932"}, {"ShiftJIS", "cp932"},
{"WIN932", "cp932"}, {"WIN932", "cp932"},
{"Windows932", "cp932"}, {"Windows932", "cp932"},
{"UHC", "cp949"}, {"UHC", "cp949"},
{"WIN949", "cp949"}, {"WIN949", "cp949"},
{"Windows949", "cp949"}, {"Windows949", "cp949"},
{"WIN866", "cp866"}, {"WIN866", "cp866"},
@ -385,7 +386,7 @@ static encodingPair encodings[] = {
/* {"EUC_TW", "?"}, */ /* {"EUC_TW", "?"}, */
/* {"LATIN10", "?"}, */ /* {"LATIN10", "?"}, */
/* {"ISO885916", "?"}, */ /* {"ISO885916", "?"}, */
/* {"MULE_INTERNAL", "?"}, */ /* {"MULE_INTERNAL", "?"}, */
{NULL, NULL} {NULL, NULL}
}; };
@ -421,14 +422,14 @@ static struct {
{ "psycopg2.InterfaceError", &InterfaceError, &Error, InterfaceError_doc }, { "psycopg2.InterfaceError", &InterfaceError, &Error, InterfaceError_doc },
{ "psycopg2.DatabaseError", &DatabaseError, &Error, DatabaseError_doc }, { "psycopg2.DatabaseError", &DatabaseError, &Error, DatabaseError_doc },
{ "psycopg2.InternalError", &InternalError, &DatabaseError, InternalError_doc }, { "psycopg2.InternalError", &InternalError, &DatabaseError, InternalError_doc },
{ "psycopg2.OperationalError", &OperationalError, &DatabaseError, { "psycopg2.OperationalError", &OperationalError, &DatabaseError,
OperationalError_doc }, OperationalError_doc },
{ "psycopg2.ProgrammingError", &ProgrammingError, &DatabaseError, { "psycopg2.ProgrammingError", &ProgrammingError, &DatabaseError,
ProgrammingError_doc }, ProgrammingError_doc },
{ "psycopg2.IntegrityError", &IntegrityError, &DatabaseError, { "psycopg2.IntegrityError", &IntegrityError, &DatabaseError,
IntegrityError_doc }, IntegrityError_doc },
{ "psycopg2.DataError", &DataError, &DatabaseError, DataError_doc }, { "psycopg2.DataError", &DataError, &DatabaseError, DataError_doc },
{ "psycopg2.NotSupportedError", &NotSupportedError, &DatabaseError, { "psycopg2.NotSupportedError", &NotSupportedError, &DatabaseError,
NotSupportedError_doc }, NotSupportedError_doc },
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
@ -439,7 +440,7 @@ psyco_errors_init(void)
/* the names of the exceptions here reflect the oranization of the /* the names of the exceptions here reflect the oranization of the
psycopg2 module and not the fact the the original error objects psycopg2 module and not the fact the the original error objects
live in _psycopg */ live in _psycopg */
int i; int i;
PyObject *dict; PyObject *dict;
PyObject *base; PyObject *base;
@ -474,7 +475,7 @@ psyco_errors_fill(PyObject *dict)
PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError); PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError);
PyDict_SetItemString(dict, "IntegrityError", IntegrityError); PyDict_SetItemString(dict, "IntegrityError", IntegrityError);
PyDict_SetItemString(dict, "DataError", DataError); PyDict_SetItemString(dict, "DataError", DataError);
PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError); PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError);
} }
void void
@ -493,17 +494,17 @@ psyco_errors_set(PyObject *type)
} }
/* psyco_error_new /* psyco_error_new
Create a new error of the given type with extra attributes. */ Create a new error of the given type with extra attributes. */
void void
psyco_set_error(PyObject *exc, PyObject *curs, char *msg, psyco_set_error(PyObject *exc, PyObject *curs, char *msg,
char *pgerror, char *pgcode) char *pgerror, char *pgcode)
{ {
PyObject *t; PyObject *t;
PyObject *err = PyObject_CallFunction(exc, "s", msg); PyObject *err = PyObject_CallFunction(exc, "s", msg);
if (err) { if (err) {
if (pgerror) { if (pgerror) {
t = PyString_FromString(pgerror); t = PyString_FromString(pgerror);
@ -522,16 +523,16 @@ psyco_set_error(PyObject *exc, PyObject *curs, char *msg,
} }
PyObject_SetAttrString(err, "pgcode", t); PyObject_SetAttrString(err, "pgcode", t);
Py_DECREF(t); Py_DECREF(t);
if (curs) if (curs)
PyObject_SetAttrString(err, "cursor", curs); PyObject_SetAttrString(err, "cursor", curs);
else else
PyObject_SetAttrString(err, "cursor", Py_None); PyObject_SetAttrString(err, "cursor", Py_None);
PyErr_SetObject(exc, err); PyErr_SetObject(exc, err);
Py_DECREF(err); Py_DECREF(err);
} }
} }
/* psyco_decimal_init /* psyco_decimal_init
@ -589,7 +590,7 @@ static PyMethodDef psycopgMethods[] = {
METH_VARARGS, psyco_TimestampFromTicks_doc}, METH_VARARGS, psyco_TimestampFromTicks_doc},
{"List", (PyCFunction)psyco_List, {"List", (PyCFunction)psyco_List,
METH_VARARGS, psyco_List_doc}, METH_VARARGS, psyco_List_doc},
#ifdef HAVE_MXDATETIME #ifdef HAVE_MXDATETIME
{"DateFromMx", (PyCFunction)psyco_DateFromMx, {"DateFromMx", (PyCFunction)psyco_DateFromMx,
METH_VARARGS, psyco_DateFromMx_doc}, METH_VARARGS, psyco_DateFromMx_doc},
@ -598,7 +599,7 @@ static PyMethodDef psycopgMethods[] = {
{"TimestampFromMx", (PyCFunction)psyco_TimestampFromMx, {"TimestampFromMx", (PyCFunction)psyco_TimestampFromMx,
METH_VARARGS, psyco_TimestampFromMx_doc}, METH_VARARGS, psyco_TimestampFromMx_doc},
{"IntervalFromMx", (PyCFunction)psyco_IntervalFromMx, {"IntervalFromMx", (PyCFunction)psyco_IntervalFromMx,
METH_VARARGS, psyco_IntervalFromMx_doc}, METH_VARARGS, psyco_IntervalFromMx_doc},
#endif #endif
#ifdef HAVE_PYDATETIME #ifdef HAVE_PYDATETIME
@ -609,7 +610,7 @@ static PyMethodDef psycopgMethods[] = {
{"TimestampFromPy", (PyCFunction)psyco_TimestampFromPy, {"TimestampFromPy", (PyCFunction)psyco_TimestampFromPy,
METH_VARARGS, psyco_TimestampFromPy_doc}, METH_VARARGS, psyco_TimestampFromPy_doc},
{"IntervalFromPy", (PyCFunction)psyco_IntervalFromPy, {"IntervalFromPy", (PyCFunction)psyco_IntervalFromPy,
METH_VARARGS, psyco_IntervalFromPy_doc}, METH_VARARGS, psyco_IntervalFromPy_doc},
#endif #endif
{NULL, NULL, 0, NULL} /* Sentinel */ {NULL, NULL, 0, NULL} /* Sentinel */
@ -619,7 +620,7 @@ PyMODINIT_FUNC
init_psycopg(void) init_psycopg(void)
{ {
static void *PSYCOPG_API[PSYCOPG_API_pointers]; static void *PSYCOPG_API[PSYCOPG_API_pointers];
PyObject *module, *dict; PyObject *module, *dict;
PyObject *c_api_object; PyObject *c_api_object;
@ -635,7 +636,7 @@ init_psycopg(void)
asisType.ob_type = &PyType_Type; asisType.ob_type = &PyType_Type;
listType.ob_type = &PyType_Type; listType.ob_type = &PyType_Type;
chunkType.ob_type = &PyType_Type; chunkType.ob_type = &PyType_Type;
if (PyType_Ready(&connectionType) == -1) return; if (PyType_Ready(&connectionType) == -1) return;
if (PyType_Ready(&cursorType) == -1) return; if (PyType_Ready(&cursorType) == -1) return;
if (PyType_Ready(&typecastType) == -1) return; if (PyType_Ready(&typecastType) == -1) return;
@ -645,18 +646,18 @@ init_psycopg(void)
if (PyType_Ready(&asisType) == -1) return; if (PyType_Ready(&asisType) == -1) return;
if (PyType_Ready(&listType) == -1) return; if (PyType_Ready(&listType) == -1) return;
if (PyType_Ready(&chunkType) == -1) return; if (PyType_Ready(&chunkType) == -1) return;
#ifdef HAVE_PYBOOL #ifdef HAVE_PYBOOL
pbooleanType.ob_type = &PyType_Type; pbooleanType.ob_type = &PyType_Type;
if (PyType_Ready(&pbooleanType) == -1) return; if (PyType_Ready(&pbooleanType) == -1) return;
#endif #endif
/* import mx.DateTime module, if necessary */ /* import mx.DateTime module, if necessary */
#ifdef HAVE_MXDATETIME #ifdef HAVE_MXDATETIME
mxdatetimeType.ob_type = &PyType_Type; mxdatetimeType.ob_type = &PyType_Type;
if (PyType_Ready(&mxdatetimeType) == -1) return; if (PyType_Ready(&mxdatetimeType) == -1) return;
if (mxDateTime_ImportModuleAndAPI() != 0) { if (mxDateTime_ImportModuleAndAPI() != 0) {
Dprintf("initpsycopg: why marc hide mx.DateTime again?!"); Dprintf("initpsycopg: why marc hide mx.DateTime again?!");
PyErr_SetString(PyExc_ImportError, "can't import mx.DateTime module"); PyErr_SetString(PyExc_ImportError, "can't import mx.DateTime module");
return; return;
} }
@ -667,7 +668,7 @@ init_psycopg(void)
#ifdef HAVE_PYDATETIME #ifdef HAVE_PYDATETIME
pyDateTimeModuleP = PyImport_ImportModule("datetime"); pyDateTimeModuleP = PyImport_ImportModule("datetime");
if (pyDateTimeModuleP == NULL) { if (pyDateTimeModuleP == NULL) {
Dprintf("initpsycopg: can't import datetime module"); Dprintf("initpsycopg: can't import datetime module");
PyErr_SetString(PyExc_ImportError, "can't import datetime module"); PyErr_SetString(PyExc_ImportError, "can't import datetime module");
return; return;
} }
@ -680,20 +681,20 @@ init_psycopg(void)
pyTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "time"); pyTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "time");
pyDateTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "datetime"); pyDateTimeTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "datetime");
pyDeltaTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "timedelta"); pyDeltaTypeP = PyObject_GetAttrString(pyDateTimeModuleP, "timedelta");
#endif #endif
/* import psycopg2.tz anyway (TODO: replace with C-level module?) */ /* import psycopg2.tz anyway (TODO: replace with C-level module?) */
pyPsycopgTzModule = PyImport_ImportModule("psycopg2.tz"); pyPsycopgTzModule = PyImport_ImportModule("psycopg2.tz");
if (pyPsycopgTzModule == NULL) { if (pyPsycopgTzModule == NULL) {
Dprintf("initpsycopg: can't import psycopg2.tz module"); Dprintf("initpsycopg: can't import psycopg2.tz module");
PyErr_SetString(PyExc_ImportError, "can't import psycopg2.tz module"); PyErr_SetString(PyExc_ImportError, "can't import psycopg2.tz module");
return; return;
} }
pyPsycopgTzLOCAL = pyPsycopgTzLOCAL =
PyObject_GetAttrString(pyPsycopgTzModule, "LOCAL"); PyObject_GetAttrString(pyPsycopgTzModule, "LOCAL");
pyPsycopgTzFixedOffsetTimezone = pyPsycopgTzFixedOffsetTimezone =
PyObject_GetAttrString(pyPsycopgTzModule, "FixedOffsetTimezone"); PyObject_GetAttrString(pyPsycopgTzModule, "FixedOffsetTimezone");
/* initialize the module and grab module's dictionary */ /* initialize the module and grab module's dictionary */
module = Py_InitModule("_psycopg", psycopgMethods); module = Py_InitModule("_psycopg", psycopgMethods);
dict = PyModule_GetDict(module); dict = PyModule_GetDict(module);
@ -710,33 +711,33 @@ init_psycopg(void)
psycoEncodings = PyDict_New(); psycoEncodings = PyDict_New();
psyco_encodings_fill(psycoEncodings); psyco_encodings_fill(psycoEncodings);
psyco_decimal_init(); psyco_decimal_init();
/* set some module's parameters */ /* set some module's parameters */
PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION); PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION);
PyModule_AddStringConstant(module, "__doc__", "psycopg PostgreSQL driver"); PyModule_AddStringConstant(module, "__doc__", "psycopg PostgreSQL driver");
PyModule_AddObject(module, "apilevel", PyString_FromString(APILEVEL)); PyModule_AddObject(module, "apilevel", PyString_FromString(APILEVEL));
PyModule_AddObject(module, "threadsafety", PyInt_FromLong(THREADSAFETY)); PyModule_AddObject(module, "threadsafety", PyInt_FromLong(THREADSAFETY));
PyModule_AddObject(module, "paramstyle", PyString_FromString(PARAMSTYLE)); PyModule_AddObject(module, "paramstyle", PyString_FromString(PARAMSTYLE));
/* put new types in module dictionary */ /* put new types in module dictionary */
PyModule_AddObject(module, "connection", (PyObject*)&connectionType); PyModule_AddObject(module, "connection", (PyObject*)&connectionType);
PyModule_AddObject(module, "cursor", (PyObject*)&cursorType); PyModule_AddObject(module, "cursor", (PyObject*)&cursorType);
PyModule_AddObject(module, "ISQLQuote", (PyObject*)&isqlquoteType); PyModule_AddObject(module, "ISQLQuote", (PyObject*)&isqlquoteType);
/* encodings dictionary in module dictionary */ /* encodings dictionary in module dictionary */
PyModule_AddObject(module, "encodings", psycoEncodings); PyModule_AddObject(module, "encodings", psycoEncodings);
/* initialize default set of typecasters */ /* initialize default set of typecasters */
typecast_init(dict); typecast_init(dict);
/* initialize microprotocols layer */ /* initialize microprotocols layer */
microprotocols_init(dict); microprotocols_init(dict);
psyco_adapters_init(dict); psyco_adapters_init(dict);
/* create a standard set of exceptions and add them to the module's dict */ /* create a standard set of exceptions and add them to the module's dict */
psyco_errors_init(); psyco_errors_init();
psyco_errors_fill(dict); psyco_errors_fill(dict);
/* Solve win32 build issue about non-constant initializer element */ /* Solve win32 build issue about non-constant initializer element */
cursorType.tp_alloc = PyType_GenericAlloc; cursorType.tp_alloc = PyType_GenericAlloc;
binaryType.tp_alloc = PyType_GenericAlloc; binaryType.tp_alloc = PyType_GenericAlloc;
@ -747,7 +748,7 @@ init_psycopg(void)
qstringType.tp_alloc = PyType_GenericAlloc; qstringType.tp_alloc = PyType_GenericAlloc;
listType.tp_alloc = PyType_GenericAlloc; listType.tp_alloc = PyType_GenericAlloc;
chunkType.tp_alloc = PyType_GenericAlloc; chunkType.tp_alloc = PyType_GenericAlloc;
#ifdef HAVE_PYDATETIME #ifdef HAVE_PYDATETIME
pydatetimeType.tp_alloc = PyType_GenericAlloc; pydatetimeType.tp_alloc = PyType_GenericAlloc;
#endif #endif

View File

@ -22,12 +22,13 @@
#ifndef PSYCOPG_PYTHON_H #ifndef PSYCOPG_PYTHON_H
#define PSYCOPG_PYTHON_H 1 #define PSYCOPG_PYTHON_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
/* python < 2.2 does not have PyMemeberDef */ /* python < 2.2 does not have PyMemeberDef */
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 2
#define PyMemberDef memberlist #define PyMemberDef memberlist
#endif #endif
/* PyObject_TypeCheck introduced in 2.2 */ /* PyObject_TypeCheck introduced in 2.2 */

View File

@ -19,6 +19,7 @@
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#include <structmember.h> #include <structmember.h>
@ -52,9 +53,9 @@ typecast_parse_date(char* s, char** t, int* len,
int* year, int* month, int* day) int* year, int* month, int* day)
{ {
int acc = -1, cz = 0; int acc = -1, cz = 0;
Dprintf("typecast_parse_date: len = %d, s = %s", *len, s); Dprintf("typecast_parse_date: len = %d, s = %s", *len, s);
while (cz < 3 && *len > 0 && *s) { while (cz < 3 && *len > 0 && *s) {
switch (*s) { switch (*s) {
case '-': case '-':
@ -67,7 +68,7 @@ typecast_parse_date(char* s, char** t, int* len,
break; break;
default: default:
acc = (acc == -1 ? 0 : acc*10) + ((int)*s - (int)'0'); acc = (acc == -1 ? 0 : acc*10) + ((int)*s - (int)'0');
break; break;
} }
s++; (*len)--; s++; (*len)--;
@ -77,7 +78,7 @@ typecast_parse_date(char* s, char** t, int* len,
*day = acc; *day = acc;
cz += 1; cz += 1;
} }
if (t != NULL) *t = s; if (t != NULL) *t = s;
return cz; return cz;
} }
@ -89,12 +90,12 @@ typecast_parse_time(char* s, char** t, int* len,
int acc = -1, cz = 0; int acc = -1, cz = 0;
int tzs = 1, tzhh = 0, tzmm = 0; int tzs = 1, tzhh = 0, tzmm = 0;
int usd = 0; int usd = 0;
/* sets microseconds and timezone to 0 because they may be missing */ /* sets microseconds and timezone to 0 because they may be missing */
*us = *tz = 0; *us = *tz = 0;
Dprintf("typecast_parse_time: len = %d, s = %s", *len, s); Dprintf("typecast_parse_time: len = %d, s = %s", *len, s);
while (cz < 6 && *len > 0 && *s) { while (cz < 6 && *len > 0 && *s) {
switch (*s) { switch (*s) {
case ':': case ':':
@ -123,7 +124,7 @@ typecast_parse_time(char* s, char** t, int* len,
default: default:
acc = (acc == -1 ? 0 : acc*10) + ((int)*s - (int)'0'); acc = (acc == -1 ? 0 : acc*10) + ((int)*s - (int)'0');
if (cz == 3) usd += 1; if (cz == 3) usd += 1;
break; break;
} }
s++; (*len)--; s++; (*len)--;
@ -136,13 +137,13 @@ typecast_parse_time(char* s, char** t, int* len,
else if (cz == 5) tzmm = acc; else if (cz == 5) tzmm = acc;
} }
if (t != NULL) *t = s; if (t != NULL) *t = s;
*tz = tzs * tzhh*60 + tzmm; *tz = tzs * tzhh*60 + tzmm;
if (*us != 0.0) { if (*us != 0.0) {
while (usd++ < 6) *us *= 10.0; while (usd++ < 6) *us *= 10.0;
} }
return cz; return cz;
} }
@ -168,7 +169,7 @@ typecastObject_initlist typecast_pydatetime[] = {
{"PYDATETIME", typecast_DATETIME_types, typecast_PYDATETIME_cast}, {"PYDATETIME", typecast_DATETIME_types, typecast_PYDATETIME_cast},
{"PYTIME", typecast_TIME_types, typecast_PYTIME_cast}, {"PYTIME", typecast_TIME_types, typecast_PYTIME_cast},
{"PYDATE", typecast_DATE_types, typecast_PYDATE_cast}, {"PYDATE", typecast_DATE_types, typecast_PYDATE_cast},
{"PYINTERVAL", typecast_INTERVAL_types, typecast_PYINTERVAL_cast}, {"PYINTERVAL", typecast_INTERVAL_types, typecast_PYINTERVAL_cast},
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };
#endif #endif
@ -179,7 +180,7 @@ typecastObject_initlist typecast_mxdatetime[] = {
{"MXDATETIME", typecast_DATETIME_types, typecast_MXDATE_cast}, {"MXDATETIME", typecast_DATETIME_types, typecast_MXDATE_cast},
{"MXTIME", typecast_TIME_types, typecast_MXTIME_cast}, {"MXTIME", typecast_TIME_types, typecast_MXTIME_cast},
{"MXDATE", typecast_DATE_types, typecast_MXDATE_cast}, {"MXDATE", typecast_DATE_types, typecast_MXDATE_cast},
{"MXINTERVAL", typecast_INTERVAL_types, typecast_MXINTERVAL_cast}, {"MXINTERVAL", typecast_INTERVAL_types, typecast_MXINTERVAL_cast},
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };
#endif #endif
@ -203,20 +204,20 @@ int
typecast_init(PyObject *dict) typecast_init(PyObject *dict)
{ {
int i; int i;
/* create type dictionary and put it in module namespace */ /* create type dictionary and put it in module namespace */
psyco_types = PyDict_New(); psyco_types = PyDict_New();
psyco_binary_types = PyDict_New(); psyco_binary_types = PyDict_New();
if (!psyco_types || !psyco_binary_types) { if (!psyco_types || !psyco_binary_types) {
Py_XDECREF(psyco_types); Py_XDECREF(psyco_types);
Py_XDECREF(psyco_binary_types); Py_XDECREF(psyco_binary_types);
return -1; return -1;
} }
PyDict_SetItemString(dict, "string_types", psyco_types); PyDict_SetItemString(dict, "string_types", psyco_types);
PyDict_SetItemString(dict, "binary_types", psyco_binary_types); PyDict_SetItemString(dict, "binary_types", psyco_binary_types);
/* insert the cast types into the 'types' dictionary and register them in /* insert the cast types into the 'types' dictionary and register them in
the module dictionary */ the module dictionary */
for (i = 0; typecast_builtins[i].name != NULL; i++) { for (i = 0; typecast_builtins[i].name != NULL; i++) {
@ -235,7 +236,7 @@ typecast_init(PyObject *dict)
psyco_default_binary_cast = (PyObject *)t; psyco_default_binary_cast = (PyObject *)t;
} }
} }
/* create and save a default cast object (but does not register it) */ /* create and save a default cast object (but does not register it) */
psyco_default_cast = typecast_from_c(&typecast_default, dict); psyco_default_cast = typecast_from_c(&typecast_default, dict);
@ -258,7 +259,7 @@ typecast_init(PyObject *dict)
PyDict_SetItem(dict, t->name, (PyObject *)t); PyDict_SetItem(dict, t->name, (PyObject *)t);
} }
#endif #endif
return 0; return 0;
} }
@ -270,9 +271,11 @@ typecast_add(PyObject *obj, PyObject *dict, int binary)
Py_ssize_t len, i; Py_ssize_t len, i;
typecastObject *type = (typecastObject *)obj; typecastObject *type = (typecastObject *)obj;
Dprintf("typecast_add: object at %p, values refcnt = %d", Dprintf("typecast_add: object at %p, values refcnt = "
obj, type->values->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
obj, type->values->ob_refcnt
);
if (dict == NULL) if (dict == NULL)
dict = (binary ? psyco_binary_types : psyco_types); dict = (binary ? psyco_binary_types : psyco_types);
@ -302,7 +305,7 @@ typecast_cmp(PyObject *obj1, PyObject* obj2)
PyObject *number = NULL; PyObject *number = NULL;
Py_ssize_t i, j; Py_ssize_t i, j;
int res = -1; int res = -1;
if (PyObject_TypeCheck(obj2, &typecastType)) { if (PyObject_TypeCheck(obj2, &typecastType)) {
other = (typecastObject*)obj2; other = (typecastObject*)obj2;
} }
@ -311,25 +314,25 @@ typecast_cmp(PyObject *obj1, PyObject* obj2)
} }
Dprintf("typecast_cmp: other = %p, number = %p", other, number); Dprintf("typecast_cmp: other = %p, number = %p", other, number);
for (i=0; i < PyObject_Length(self->values) && res == -1; i++) { for (i=0; i < PyObject_Length(self->values) && res == -1; i++) {
long int val = PyInt_AsLong(PyTuple_GET_ITEM(self->values, i)); long int val = PyInt_AsLong(PyTuple_GET_ITEM(self->values, i));
if (other != NULL) { if (other != NULL) {
for (j=0; j < PyObject_Length(other->values); j++) { for (j=0; j < PyObject_Length(other->values); j++) {
if (PyInt_AsLong(PyTuple_GET_ITEM(other->values, j)) == val) { if (PyInt_AsLong(PyTuple_GET_ITEM(other->values, j)) == val) {
res = 0; break; res = 0; break;
} }
} }
} }
else if (number != NULL) { else if (number != NULL) {
if (PyInt_AsLong(number) == val) { if (PyInt_AsLong(number) == val) {
res = 0; break; res = 0; break;
} }
} }
} }
Py_XDECREF(number); Py_XDECREF(number);
return res; return res;
} }
@ -339,29 +342,29 @@ typecast_richcompare(PyObject *obj1, PyObject* obj2, int opid)
{ {
PyObject *result = NULL; PyObject *result = NULL;
int res = typecast_cmp(obj1, obj2); int res = typecast_cmp(obj1, obj2);
if (PyErr_Occurred()) return NULL; if (PyErr_Occurred()) return NULL;
if ((opid == Py_EQ && res == 0) || (opid != Py_EQ && res != 0)) if ((opid == Py_EQ && res == 0) || (opid != Py_EQ && res != 0))
result = Py_True; result = Py_True;
else else
result = Py_False; result = Py_False;
Py_INCREF(result); Py_INCREF(result);
return result; return result;
} }
static struct PyMemberDef typecastObject_members[] = { static struct PyMemberDef typecastObject_members[] = {
{"name", T_OBJECT, OFFSETOF(name), RO}, {"name", T_OBJECT, OFFSETOF(name), RO},
{"values", T_OBJECT, OFFSETOF(values), RO}, {"values", T_OBJECT, OFFSETOF(values), RO},
{NULL} {NULL}
}; };
static void static void
typecast_dealloc(PyObject *obj) typecast_dealloc(PyObject *obj)
{ {
typecastObject *self = (typecastObject*)obj; typecastObject *self = (typecastObject*)obj;
Py_XDECREF(self->values); Py_XDECREF(self->values);
Py_XDECREF(self->name); Py_XDECREF(self->name);
Py_XDECREF(self->pcast); Py_XDECREF(self->pcast);
@ -371,9 +374,9 @@ typecast_dealloc(PyObject *obj)
static PyObject * static PyObject *
typecast_call(PyObject *obj, PyObject *args, PyObject *kwargs) typecast_call(PyObject *obj, PyObject *args, PyObject *kwargs)
{ {
PyObject *string, *cursor; PyObject *string, *cursor;
if (!PyArg_ParseTuple(args, "OO", &string, &cursor)) { if (!PyArg_ParseTuple(args, "OO", &string, &cursor)) {
return NULL; return NULL;
} }
@ -389,9 +392,9 @@ PyTypeObject typecastType = {
"psycopg2._psycopg.type", "psycopg2._psycopg.type",
sizeof(typecastObject), sizeof(typecastObject),
0, 0,
typecast_dealloc, /*tp_dealloc*/ typecast_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
typecast_cmp, /*tp_compare*/ typecast_cmp, /*tp_compare*/
@ -409,7 +412,7 @@ PyTypeObject typecastType = {
Py_TPFLAGS_HAVE_RICHCOMPARE, /*tp_flags*/ Py_TPFLAGS_HAVE_RICHCOMPARE, /*tp_flags*/
"psycopg type-casting object", /*tp_doc*/ "psycopg type-casting object", /*tp_doc*/
0, /*tp_traverse*/ 0, /*tp_traverse*/
0, /*tp_clear*/ 0, /*tp_clear*/
@ -426,11 +429,11 @@ PyTypeObject typecastType = {
0, /*tp_getset*/ 0, /*tp_getset*/
0, /*tp_base*/ 0, /*tp_base*/
0, /*tp_dict*/ 0, /*tp_dict*/
0, /*tp_descr_get*/ 0, /*tp_descr_get*/
0, /*tp_descr_set*/ 0, /*tp_descr_set*/
0, /*tp_dictoffset*/ 0, /*tp_dictoffset*/
0, /*tp_init*/ 0, /*tp_init*/
0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
0, /*tp_new*/ 0, /*tp_new*/
@ -451,11 +454,12 @@ typecast_new(PyObject *name, PyObject *values, PyObject *cast, PyObject *base)
obj = PyObject_NEW(typecastObject, &typecastType); obj = PyObject_NEW(typecastObject, &typecastType);
if (obj == NULL) return NULL; if (obj == NULL) return NULL;
Dprintf("typecast_new: new type at = %p, refcnt = %d", obj, obj->ob_refcnt); Dprintf("typecast_new: new type at = %p, refcnt = " FORMAT_CODE_PY_SSIZE_T,
obj, obj->ob_refcnt);
Py_INCREF(values); Py_INCREF(values);
obj->values = values; obj->values = values;
if (name) { if (name) {
Py_INCREF(name); Py_INCREF(name);
obj->name = name; obj->name = name;
@ -476,26 +480,26 @@ typecast_new(PyObject *name, PyObject *values, PyObject *cast, PyObject *base)
Py_INCREF(cast); Py_INCREF(cast);
obj->pcast = cast; obj->pcast = cast;
} }
Dprintf("typecast_new: typecast object created at %p", obj); Dprintf("typecast_new: typecast object created at %p", obj);
return (PyObject *)obj; return (PyObject *)obj;
} }
PyObject * PyObject *
typecast_from_python(PyObject *self, PyObject *args, PyObject *keywds) typecast_from_python(PyObject *self, PyObject *args, PyObject *keywds)
{ {
PyObject *v, *name, *cast = NULL, *base = NULL; PyObject *v, *name = NULL, *cast = NULL, *base = NULL;
static char *kwlist[] = {"values", "name", "castobj", "baseobj", NULL}; static char *kwlist[] = {"values", "name", "castobj", "baseobj", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!|O!OO", kwlist, if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!|O!OO", kwlist,
&PyTuple_Type, &v, &PyTuple_Type, &v,
&PyString_Type, &name, &PyString_Type, &name,
&cast, &base)) { &cast, &base)) {
return NULL; return NULL;
} }
return typecast_new(name, v, cast, base); return typecast_new(name, v, cast, base);
} }
@ -517,18 +521,18 @@ typecast_from_c(typecastObject_initlist *type, PyObject *dict)
} }
while (type->values[len] != 0) len++; while (type->values[len] != 0) len++;
tuple = PyTuple_New(len); tuple = PyTuple_New(len);
if (!tuple) return NULL; if (!tuple) return NULL;
for (i = 0; i < len ; i++) { for (i = 0; i < len ; i++) {
PyTuple_SET_ITEM(tuple, i, PyInt_FromLong(type->values[i])); PyTuple_SET_ITEM(tuple, i, PyInt_FromLong(type->values[i]));
} }
obj = (typecastObject *) obj = (typecastObject *)
typecast_new(PyString_FromString(type->name), tuple, NULL, base); typecast_new(PyString_FromString(type->name), tuple, NULL, base);
if (obj) { if (obj) {
obj->ccast = type->cast; obj->ccast = type->cast;
obj->pcast = NULL; obj->pcast = NULL;
@ -545,7 +549,7 @@ typecast_cast(PyObject *obj, char *str, Py_ssize_t len, PyObject *curs)
/* we don't incref, the caster *can't* die at this point */ /* we don't incref, the caster *can't* die at this point */
old = ((cursorObject*)curs)->caster; old = ((cursorObject*)curs)->caster;
((cursorObject*)curs)->caster = obj; ((cursorObject*)curs)->caster = obj;
if (self->ccast) { if (self->ccast) {
res = self->ccast(str, len, curs); res = self->ccast(str, len, curs);
} }

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_TYPECAST_H #ifndef PSYCOPG_TYPECAST_H
#define PSYCOPG_TYPECAST_H 1 #define PSYCOPG_TYPECAST_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -60,7 +61,7 @@ typedef struct {
/* the type dictionary, much faster to access it globally */ /* the type dictionary, much faster to access it globally */
extern PyObject *psyco_types; extern PyObject *psyco_types;
extern PyObject *psyco_binary_types; extern PyObject *psyco_binary_types;
/* the default casting objects, used when no other objects are available */ /* the default casting objects, used when no other objects are available */
extern PyObject *psyco_default_cast; extern PyObject *psyco_default_cast;
extern PyObject *psyco_default_binary_cast; extern PyObject *psyco_default_binary_cast;
@ -81,5 +82,5 @@ extern PyObject *typecast_from_python(
/* the function used to dispatch typecasting calls */ /* the function used to dispatch typecasting calls */
extern PyObject *typecast_cast( extern PyObject *typecast_cast(
PyObject *self, char *str, Py_ssize_t len, PyObject *curs); PyObject *self, char *str, Py_ssize_t len, PyObject *curs);
#endif /* !defined(PSYCOPG_TYPECAST_H) */ #endif /* !defined(PSYCOPG_TYPECAST_H) */

View File

@ -27,9 +27,9 @@ static int
typecast_array_cleanup(char **str, int *len) typecast_array_cleanup(char **str, int *len)
{ {
int i, depth = 1; int i, depth = 1;
if ((*str)[0] != '[') return -1; if ((*str)[0] != '[') return -1;
for (i=1 ; depth > 0 && i < *len ; i++) { for (i=1 ; depth > 0 && i < *len ; i++) {
if ((*str)[i] == '[') if ((*str)[i] == '[')
depth += 1; depth += 1;
@ -37,7 +37,7 @@ typecast_array_cleanup(char **str, int *len)
depth -= 1; depth -= 1;
} }
if ((*str)[i] != '=') return -1; if ((*str)[i] != '=') return -1;
*str = &((*str)[i+1]); *str = &((*str)[i+1]);
*len = *len - i - 1; *len = *len - i - 1;
return 0; return 0;
@ -83,7 +83,7 @@ typecast_array_tokenize(char *str, int strlength,
q = 0; /* if q is odd we're inside quotes */ q = 0; /* if q is odd we're inside quotes */
b = 0; /* if b is 1 we just encountered a backslash */ b = 0; /* if b is 1 we just encountered a backslash */
res = ASCAN_TOKEN; res = ASCAN_TOKEN;
for (i = *pos ; i < strlength ; i++) { for (i = *pos ; i < strlength ; i++) {
switch (str[i]) { switch (str[i]) {
case '"': case '"':
@ -122,21 +122,21 @@ typecast_array_tokenize(char *str, int strlength,
if (str[*pos] == '"') { if (str[*pos] == '"') {
*pos += 1; *pos += 1;
l -= 2; l -= 2;
*quotes = 1; *quotes = 1;
} }
if (res == ASCAN_QUOTED) { if (res == ASCAN_QUOTED) {
char *buffer = PyMem_Malloc(l+1); char *buffer = PyMem_Malloc(l+1);
if (buffer == NULL) return ASCAN_ERROR; if (buffer == NULL) return ASCAN_ERROR;
*token = buffer; *token = buffer;
for (j = *pos; j < *pos+l; j++) { for (j = *pos; j < *pos+l; j++) {
if (str[j] != '\\' if (str[j] != '\\'
|| (j > *pos && str[j-1] == '\\')) || (j > *pos && str[j-1] == '\\'))
*(buffer++) = str[j]; *(buffer++) = str[j];
} }
*buffer = '\0'; *buffer = '\0';
*length = buffer - *token; *length = buffer - *token;
} }
@ -146,7 +146,7 @@ typecast_array_tokenize(char *str, int strlength,
} }
*pos = i; *pos = i;
/* skip the comma and set position to the start of next token */ /* skip the comma and set position to the start of next token */
if (str[i] == ',') *pos += 1; if (str[i] == ',') *pos += 1;
@ -162,22 +162,22 @@ typecast_array_scan(char *str, int strlength,
PyObject *stack[MAX_DIMENSIONS]; PyObject *stack[MAX_DIMENSIONS];
int stack_index = 0; int stack_index = 0;
while (1) { while (1) {
token = NULL; token = NULL;
state = typecast_array_tokenize(str, strlength, state = typecast_array_tokenize(str, strlength,
&pos, &token, &length, &quotes); &pos, &token, &length, &quotes);
Dprintf("typecast_array_scan: state = %d, length = %d, token = '%s'", Dprintf("typecast_array_scan: state = %d, length = %d, token = '%s'",
state, length, token); state, length, token);
if (state == ASCAN_TOKEN || state == ASCAN_QUOTED) { if (state == ASCAN_TOKEN || state == ASCAN_QUOTED) {
PyObject *obj; PyObject *obj;
if (!quotes && length == 4 if (!quotes && length == 4
&& (token[0] == 'n' || token[0] == 'N') && (token[0] == 'n' || token[0] == 'N')
&& (token[1] == 'u' || token[1] == 'U') && (token[1] == 'u' || token[1] == 'U')
&& (token[2] == 'l' || token[2] == 'L') && (token[2] == 'l' || token[2] == 'L')
&& (token[3] == 'l' || token[3] == 'L')) && (token[3] == 'l' || token[3] == 'L'))
obj = typecast_cast(base, NULL, 0, curs); obj = typecast_cast(base, NULL, 0, curs);
else else
obj = typecast_cast(base, token, length, curs); obj = typecast_cast(base, token, length, curs);
/* before anything else we free the memory */ /* before anything else we free the memory */
@ -189,7 +189,7 @@ typecast_array_scan(char *str, int strlength,
} }
else if (state == ASCAN_BEGIN) { else if (state == ASCAN_BEGIN) {
PyObject *sub = PyList_New(0); PyObject *sub = PyList_New(0);
if (sub == NULL) return 0; if (sub == NULL) return 0;
PyList_Append(array, sub); PyList_Append(array, sub);
@ -201,7 +201,7 @@ typecast_array_scan(char *str, int strlength,
stack[stack_index++] = array; stack[stack_index++] = array;
array = sub; array = sub;
} }
else if (state == ASCAN_ERROR) { else if (state == ASCAN_ERROR) {
return 0; return 0;
} }
@ -222,13 +222,13 @@ typecast_array_scan(char *str, int strlength,
/** GENERIC - a generic typecaster that can be used when no special actions /** GENERIC - a generic typecaster that can be used when no special actions
have to be taken on the single items **/ have to be taken on the single items **/
static PyObject * static PyObject *
typecast_GENERIC_ARRAY_cast(char *str, int len, PyObject *curs) typecast_GENERIC_ARRAY_cast(char *str, int len, PyObject *curs)
{ {
PyObject *obj = NULL; PyObject *obj = NULL;
PyObject *base = ((typecastObject*)((cursorObject*)curs)->caster)->bcast; PyObject *base = ((typecastObject*)((cursorObject*)curs)->caster)->bcast;
Dprintf("typecast_GENERIC_ARRAY_cast: str = '%s', len = %d", str, len); Dprintf("typecast_GENERIC_ARRAY_cast: str = '%s', len = %d", str, len);
if (str == NULL) {Py_INCREF(Py_None); return Py_None;} if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
@ -240,7 +240,7 @@ typecast_GENERIC_ARRAY_cast(char *str, int len, PyObject *curs)
} }
Dprintf("typecast_GENERIC_ARRAY_cast: str = '%s', len = %d", str, len); Dprintf("typecast_GENERIC_ARRAY_cast: str = '%s', len = %d", str, len);
obj = PyList_New(0); obj = PyList_New(0);
/* scan the array skipping the first level of {} */ /* scan the array skipping the first level of {} */
@ -248,7 +248,7 @@ typecast_GENERIC_ARRAY_cast(char *str, int len, PyObject *curs)
Py_DECREF(obj); Py_DECREF(obj);
obj = NULL; obj = NULL;
} }
return obj; return obj;
} }

View File

@ -33,8 +33,10 @@
static void static void
chunk_dealloc(chunkObject *self) chunk_dealloc(chunkObject *self)
{ {
Dprintf("chunk_dealloc: deallocating memory at %p, size %d", Dprintf("chunk_dealloc: deallocating memory at %p, size "
self->base, self->len); FORMAT_CODE_PY_SSIZE_T,
self->base, self->len
);
free(self->base); free(self->base);
self->ob_type->tp_free((PyObject *) self); self->ob_type->tp_free((PyObject *) self);
} }
@ -42,12 +44,14 @@ chunk_dealloc(chunkObject *self)
static PyObject * static PyObject *
chunk_repr(chunkObject *self) chunk_repr(chunkObject *self)
{ {
return PyString_FromFormat("<memory chunk at %p size %d>", return PyString_FromFormat(
self->base, self->len); "<memory chunk at %p size " FORMAT_CODE_PY_SSIZE_T ">",
self->base, self->len
);
} }
static int static Py_ssize_t
chunk_getreadbuffer(chunkObject *self, int segment, void **ptr) chunk_getreadbuffer(chunkObject *self, Py_ssize_t segment, void **ptr)
{ {
if (segment != 0) if (segment != 0)
{ {
@ -59,8 +63,8 @@ chunk_getreadbuffer(chunkObject *self, int segment, void **ptr)
return self->len; return self->len;
} }
static int static Py_ssize_t
chunk_getsegcount(chunkObject *self, int *lenp) chunk_getsegcount(chunkObject *self, Py_ssize_t *lenp)
{ {
if (lenp != NULL) if (lenp != NULL)
*lenp = self->len; *lenp = self->len;
@ -69,10 +73,10 @@ chunk_getsegcount(chunkObject *self, int *lenp)
static PyBufferProcs chunk_as_buffer = static PyBufferProcs chunk_as_buffer =
{ {
(getreadbufferproc) chunk_getreadbuffer, (readbufferproc) chunk_getreadbuffer,
(getwritebufferproc) NULL, (writebufferproc) NULL,
(getsegcountproc) chunk_getsegcount, (segcountproc) chunk_getsegcount,
(getcharbufferproc) NULL (charbufferproc) NULL
}; };
#define chunk_doc "memory chunk" #define chunk_doc "memory chunk"
@ -120,7 +124,7 @@ typecast_BINARY_cast_unescape(unsigned char *str, size_t *to_length)
if (dststr == NULL) return NULL; if (dststr == NULL) return NULL;
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (str[i] == '\\') { if (str[i] == '\\') {
if ( ++i < len) { if ( ++i < len) {
@ -140,17 +144,17 @@ typecast_BINARY_cast_unescape(unsigned char *str, size_t *to_length)
} }
dstptr++; dstptr++;
} }
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
*to_length = (size_t)(dstptr-dststr); *to_length = (size_t)(dstptr-dststr);
return dststr; return dststr;
} }
#define PQunescapeBytea typecast_BINARY_cast_unescape #define PQunescapeBytea typecast_BINARY_cast_unescape
#endif #endif
static PyObject * static PyObject *
typecast_BINARY_cast(char *s, int l, PyObject *curs) typecast_BINARY_cast(char *s, int l, PyObject *curs)
{ {
@ -172,12 +176,13 @@ typecast_BINARY_cast(char *s, int l, PyObject *curs)
s = buffer; s = buffer;
} }
str = (char*)PQunescapeBytea((unsigned char*)s, &len); str = (char*)PQunescapeBytea((unsigned char*)s, &len);
Dprintf("typecast_BINARY_cast: unescaped %d bytes", len); Dprintf("typecast_BINARY_cast: unescaped " FORMAT_CODE_SIZE_T " bytes",
len);
if (buffer) PyMem_Free(buffer); if (buffer) PyMem_Free(buffer);
chunk = (chunkObject *) PyObject_New(chunkObject, &chunkType); chunk = (chunkObject *) PyObject_New(chunkObject, &chunkType);
if (chunk == NULL) return NULL; if (chunk == NULL) return NULL;
chunk->base = str; chunk->base = str;
chunk->len = len; chunk->len = len;
if ((res = PyBuffer_FromObject((PyObject *)chunk, 0, len)) == NULL) if ((res = PyBuffer_FromObject((PyObject *)chunk, 0, len)) == NULL)

View File

@ -22,6 +22,7 @@
#ifndef PSYCOPG_TYPECAST_BINARY_H #ifndef PSYCOPG_TYPECAST_BINARY_H
#define PSYCOPG_TYPECAST_BINARY_H 1 #define PSYCOPG_TYPECAST_BINARY_H 1
#define PY_SSIZE_T_CLEAN
#include <Python.h> #include <Python.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -36,7 +37,7 @@ typedef struct {
PyObject_HEAD PyObject_HEAD
void *base; /* Pointer to the memory chunk. */ void *base; /* Pointer to the memory chunk. */
int len; /* Size in bytes of the memory chunk. */ Py_ssize_t len; /* Size in bytes of the memory chunk. */
} chunkObject; } chunkObject;

View File

@ -38,9 +38,9 @@ typecast_PYDATE_cast(char *str, int len, PyObject *curs)
{ {
PyObject* obj = NULL; PyObject* obj = NULL;
int n, y=0, m=0, d=0; int n, y=0, m=0, d=0;
if (str == NULL) {Py_INCREF(Py_None); return Py_None;} if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) { if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
if (str[0] == '-') { if (str[0] == '-') {
obj = PyObject_GetAttrString(pyDateTypeP, "min"); obj = PyObject_GetAttrString(pyDateTypeP, "min");
@ -59,7 +59,7 @@ typecast_PYDATE_cast(char *str, int len, PyObject *curs)
PyErr_SetString(DataError, "unable to parse date"); PyErr_SetString(DataError, "unable to parse date");
} }
else { else {
if (y > 9999) y = 9999; if (y > 9999) y = 9999;
obj = PyObject_CallFunction(pyDateTypeP, "iii", y, m, d); obj = PyObject_CallFunction(pyDateTypeP, "iii", y, m, d);
} }
} }
@ -75,9 +75,9 @@ typecast_PYDATETIME_cast(char *str, int len, PyObject *curs)
int n, y=0, m=0, d=0; int n, y=0, m=0, d=0;
int hh=0, mm=0, ss=0, us=0, tz=0; int hh=0, mm=0, ss=0, us=0, tz=0;
char *tp = NULL; char *tp = NULL;
if (str == NULL) {Py_INCREF(Py_None); return Py_None;} if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
/* check for infinity */ /* check for infinity */
if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) { if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
if (str[0] == '-') { if (str[0] == '-') {
@ -93,11 +93,11 @@ typecast_PYDATETIME_cast(char *str, int len, PyObject *curs)
n = typecast_parse_date(str, &tp, &len, &y, &m, &d); n = typecast_parse_date(str, &tp, &len, &y, &m, &d);
Dprintf("typecast_PYDATE_cast: tp = %p " Dprintf("typecast_PYDATE_cast: tp = %p "
"n = %d, len = %d, y = %d, m = %d, d = %d", "n = %d, len = %d, y = %d, m = %d, d = %d",
tp, n, len, y, m, d); tp, n, len, y, m, d);
if (n != 3) { if (n != 3) {
PyErr_SetString(DataError, "unable to parse date"); PyErr_SetString(DataError, "unable to parse date");
} }
if (len > 0) { if (len > 0) {
n = typecast_parse_time(tp, NULL, &len, &hh, &mm, &ss, &us, &tz); n = typecast_parse_time(tp, NULL, &len, &hh, &mm, &ss, &us, &tz);
Dprintf("typecast_PYDATETIME_cast: n = %d, len = %d, " Dprintf("typecast_PYDATETIME_cast: n = %d, len = %d, "
@ -107,13 +107,13 @@ typecast_PYDATETIME_cast(char *str, int len, PyObject *curs)
PyErr_SetString(DataError, "unable to parse time"); PyErr_SetString(DataError, "unable to parse time");
} }
} }
if (ss > 59) { if (ss > 59) {
mm += 1; mm += 1;
ss -= 60; ss -= 60;
} }
if (y > 9999) if (y > 9999)
y = 9999; y = 9999;
if (n == 5 && ((cursorObject*)curs)->tzinfo_factory != Py_None) { if (n == 5 && ((cursorObject*)curs)->tzinfo_factory != Py_None) {
/* we have a time zone, calculate minutes and create /* we have a time zone, calculate minutes and create
@ -124,8 +124,10 @@ typecast_PYDATETIME_cast(char *str, int len, PyObject *curs)
((cursorObject*)curs)->tzinfo_factory, "i", tz); ((cursorObject*)curs)->tzinfo_factory, "i", tz);
obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO", obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
y, m, d, hh, mm, ss, us, tzinfo); y, m, d, hh, mm, ss, us, tzinfo);
Dprintf("typecast_PYDATETIME_cast: tzinfo: %p, refcnt = %d", Dprintf("typecast_PYDATETIME_cast: tzinfo: %p, refcnt = "
tzinfo, tzinfo->ob_refcnt); FORMAT_CODE_PY_SSIZE_T,
tzinfo, tzinfo->ob_refcnt
);
Py_XDECREF(tzinfo); Py_XDECREF(tzinfo);
} }
else { else {
@ -143,14 +145,14 @@ typecast_PYTIME_cast(char *str, int len, PyObject *curs)
{ {
PyObject* obj = NULL; PyObject* obj = NULL;
int n, hh=0, mm=0, ss=0, us=0, tz=0; int n, hh=0, mm=0, ss=0, us=0, tz=0;
if (str == NULL) {Py_INCREF(Py_None); return Py_None;} if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
n = typecast_parse_time(str, NULL, &len, &hh, &mm, &ss, &us, &tz); n = typecast_parse_time(str, NULL, &len, &hh, &mm, &ss, &us, &tz);
Dprintf("typecast_PYTIME_cast: n = %d, len = %d, " Dprintf("typecast_PYTIME_cast: n = %d, len = %d, "
"hh = %d, mm = %d, ss = %d, us = %d, tz = %d", "hh = %d, mm = %d, ss = %d, us = %d, tz = %d",
n, len, hh, mm, ss, us, tz); n, len, hh, mm, ss, us, tz);
if (n < 3 || n > 5) { if (n < 3 || n > 5) {
PyErr_SetString(DataError, "unable to parse time"); PyErr_SetString(DataError, "unable to parse time");
} }
@ -161,7 +163,7 @@ typecast_PYTIME_cast(char *str, int len, PyObject *curs)
} }
obj = PyObject_CallFunction(pyTimeTypeP, "iiii", hh, mm, ss, us); obj = PyObject_CallFunction(pyTimeTypeP, "iiii", hh, mm, ss, us);
} }
return obj; return obj;
} }
/** INTERVAL - parse an interval into a timedelta object **/ /** INTERVAL - parse an interval into a timedelta object **/
@ -178,7 +180,7 @@ typecast_PYINTERVAL_cast(char *str, int len, PyObject *curs)
if (str == NULL) {Py_INCREF(Py_None); return Py_None;} if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
Dprintf("typecast_PYINTERVAL_cast: s = %s", str); Dprintf("typecast_PYINTERVAL_cast: s = %s", str);
while (len-- > 0 && *str) { while (len-- > 0 && *str) {
switch (*str) { switch (*str) {
@ -234,12 +236,12 @@ typecast_PYINTERVAL_cast(char *str, int len, PyObject *curs)
seconds = v; seconds = v;
v = 0.0; part = 6; v = 0.0; part = 6;
} }
break; break;
default: default:
break; break;
} }
str++; str++;
} }
@ -254,7 +256,7 @@ typecast_PYINTERVAL_cast(char *str, int len, PyObject *curs)
hundredths = v; hundredths = v;
hundredths = hundredths/denominator; hundredths = hundredths/denominator;
} }
/* calculates seconds */ /* calculates seconds */
if (sign < 0.0) { if (sign < 0.0) {
seconds = - (hundredths + seconds + minutes*60 + hours*3600); seconds = - (hundredths + seconds + minutes*60 + hours*3600);
@ -263,7 +265,7 @@ typecast_PYINTERVAL_cast(char *str, int len, PyObject *curs)
seconds += hundredths + minutes*60 + hours*3600; seconds += hundredths + minutes*60 + hours*3600;
} }
/* calculates days */ /* calculates days */
days += years*365 + months*30; days += years*365 + months*30;
micro = (seconds - floor(seconds)) * 1000000.0; micro = (seconds - floor(seconds)) * 1000000.0;
@ -274,7 +276,7 @@ typecast_PYINTERVAL_cast(char *str, int len, PyObject *curs)
/* psycopg defaults to using python datetime types */ /* psycopg defaults to using python datetime types */
#ifdef PSYCOPG_DEFAULT_PYDATETIME #ifdef PSYCOPG_DEFAULT_PYDATETIME
#define typecast_DATE_cast typecast_PYDATE_cast #define typecast_DATE_cast typecast_PYDATE_cast
#define typecast_TIME_cast typecast_PYTIME_cast #define typecast_TIME_cast typecast_PYTIME_cast
#define typecast_INTERVAL_cast typecast_PYINTERVAL_cast #define typecast_INTERVAL_cast typecast_PYINTERVAL_cast