summaryrefslogtreecommitdiff
path: root/psycopg
diff options
context:
space:
mode:
authorFederico Di Gregorio <fog@initd.org>2005-02-28 15:50:55 +0000
committerFederico Di Gregorio <fog@initd.org>2005-02-28 15:50:55 +0000
commitcd672525e10826231576e6eb5ab256df1bfed72c (patch)
treef6d2add7b330b9c73a950ce6fee0ea9254d12f81 /psycopg
parent1ec3c837203661efd9441e2509351156b4a53a40 (diff)
downloadpsycopg2-cd672525e10826231576e6eb5ab256df1bfed72c.tar.gz
Adaptation fixes (a lot.)
Diffstat (limited to 'psycopg')
-rw-r--r--psycopg/adapter_asis.c223
-rw-r--r--psycopg/adapter_asis.h51
-rw-r--r--psycopg/adapter_binary.c4
-rw-r--r--psycopg/adapter_datetime.c4
-rw-r--r--psycopg/adapter_mxdatetime.c4
-rw-r--r--psycopg/adapter_pboolean.c4
-rw-r--r--psycopg/cursor_type.c71
-rw-r--r--psycopg/microprotocols.c11
-rw-r--r--psycopg/microprotocols_proto.c4
-rw-r--r--psycopg/psycopgmodule.c18
10 files changed, 349 insertions, 45 deletions
diff --git a/psycopg/adapter_asis.c b/psycopg/adapter_asis.c
new file mode 100644
index 0000000..5e5fb86
--- /dev/null
+++ b/psycopg/adapter_asis.c
@@ -0,0 +1,223 @@
+/* adapter_asis.c - adapt types as they are
+ *
+ * Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
+ *
+ * This file is part of psycopg.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <Python.h>
+#include <structmember.h>
+#include <stringobject.h>
+#include <string.h>
+
+#define PSYCOPG_MODULE
+#include "psycopg/config.h"
+#include "psycopg/python.h"
+#include "psycopg/psycopg.h"
+#include "psycopg/adapter_asis.h"
+
+
+/** the AsIs object **/
+
+static PyObject *
+asis_str(asisObject *self)
+{
+ if (self->wrapped == Py_None) {
+ return PyString_FromString("NULL");
+ }
+ else {
+ return PyObject_Repr(self->wrapped);
+ }
+}
+
+PyObject *
+asis_getquoted(asisObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, "")) return NULL;
+ return asis_str(self);
+}
+
+PyObject *
+asis_prepare(asisObject *self, PyObject *args)
+{
+ PyObject *fake;
+
+ if (!PyArg_ParseTuple(args, "O", &fake)) return NULL;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/** the AsIs object */
+
+/* object member list */
+
+static struct PyMemberDef asisObject_members[] = {
+ {"adapted", T_OBJECT, offsetof(asisObject, wrapped), RO},
+ {NULL}
+};
+
+/* object method table */
+
+static PyMethodDef asisObject_methods[] = {
+ {"getquoted", (PyCFunction)asis_getquoted, METH_VARARGS,
+ "getquoted() -> wrapped object value as SQL-quoted string"},
+ /* {"prepare", (PyCFunction)asis_prepare, METH_VARARGS,
+ "prepare(conn) -> currently does nothing"}, */
+ {NULL} /* Sentinel */
+};
+
+/* initialization and finalization methods */
+
+static int
+asis_setup(asisObject *self, PyObject *obj)
+{
+ Dprintf("asis_setup: init asis object at %p, refcnt = %d",
+ self, ((PyObject *)self)->ob_refcnt);
+
+ self->wrapped = obj;
+ Py_INCREF(self->wrapped);
+
+ Dprintf("asis_setup: good asis object at %p, refcnt = %d",
+ self, ((PyObject *)self)->ob_refcnt);
+ return 0;
+}
+
+static void
+asis_dealloc(PyObject* obj)
+{
+ asisObject *self = (asisObject *)obj;
+
+ Py_XDECREF(self->wrapped);
+
+ Dprintf("asis_dealloc: deleted asis object at %p, refcnt = %d",
+ obj, obj->ob_refcnt);
+
+ obj->ob_type->tp_free(obj);
+}
+
+static int
+asis_init(PyObject *obj, PyObject *args, PyObject *kwds)
+{
+ PyObject *o;
+
+ if (!PyArg_ParseTuple(args, "O", &o))
+ return -1;
+
+ return asis_setup((asisObject *)obj, o);
+}
+
+static PyObject *
+asis_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ return type->tp_alloc(type, 0);
+}
+
+static void
+asis_del(PyObject* self)
+{
+ PyObject_Del(self);
+}
+
+static PyObject *
+asis_repr(asisObject *self)
+{
+ return PyString_FromFormat("<psycopg.AsIs object at %p>", self);
+}
+
+
+/* object type */
+
+#define asisType_doc \
+"psycopg.AsIs(str) -> new AsIs adapter object"
+
+PyTypeObject asisType = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "psycopg._psycopg.AsIs",
+ sizeof(asisObject),
+ 0,
+ asis_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+
+ 0, /*tp_compare*/
+
+ (reprfunc)asis_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+
+ 0, /*tp_call*/
+ (reprfunc)asis_str, /*tp_str*/
+
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ asisType_doc, /*tp_doc*/
+
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+
+ /* Attribute descriptor and subclassing stuff */
+
+ asisObject_methods, /*tp_methods*/
+ asisObject_members, /*tp_members*/
+ 0, /*tp_getset*/
+ 0, /*tp_base*/
+ 0, /*tp_dict*/
+
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+
+ asis_init, /*tp_init*/
+ PyType_GenericAlloc, /*tp_alloc*/
+ asis_new, /*tp_new*/
+ (freefunc)asis_del, /*tp_free Low-level free-memory routine */
+ 0, /*tp_is_gc For PyObject_IS_GC */
+ 0, /*tp_bases*/
+ 0, /*tp_mro method resolution order */
+ 0, /*tp_cache*/
+ 0, /*tp_subclasses*/
+ 0 /*tp_weaklist*/
+};
+
+
+/** module-level functions **/
+
+PyObject *
+psyco_AsIs(PyObject *module, PyObject *args)
+{
+ PyObject *obj;
+
+ if (!PyArg_ParseTuple(args, "O", &obj))
+ return NULL;
+
+ return PyObject_CallFunction((PyObject *)&asisType, "O", obj);
+}
diff --git a/psycopg/adapter_asis.h b/psycopg/adapter_asis.h
new file mode 100644
index 0000000..79e7ec4
--- /dev/null
+++ b/psycopg/adapter_asis.h
@@ -0,0 +1,51 @@
+/* adapter_asis.h - definition for the psycopg AsIs type wrapper
+ *
+ * Copyright (C) 2003-2005 Federico Di Gregorio <fog@debian.org>
+ *
+ * This file is part of psycopg.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PSYCOPG_ASIS_H
+#define PSYCOPG_ASIS_H 1
+
+#include <Python.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern PyTypeObject asisType;
+
+typedef struct {
+ PyObject HEAD;
+
+ /* this is the real object we wrap */
+ PyObject *wrapped;
+
+} asisObject;
+
+/* functions exported to psycopgmodule.c */
+
+extern PyObject *psyco_AsIs(PyObject *module, PyObject *args);
+#define psyco_AsIs_doc \
+ "psycopg.AsIs(obj) -> new AsIs wrapper object"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(PSYCOPG_ASIS_H) */
diff --git a/psycopg/adapter_binary.c b/psycopg/adapter_binary.c
index d8629d4..43be441 100644
--- a/psycopg/adapter_binary.c
+++ b/psycopg/adapter_binary.c
@@ -190,8 +190,8 @@ static struct PyMemberDef binaryObject_members[] = {
static PyMethodDef binaryObject_methods[] = {
{"getquoted", (PyCFunction)binary_getquoted, METH_VARARGS,
"getquoted() -> wrapped object value as SQL-quoted binary string"},
- {"prepare", (PyCFunction)binary_prepare, METH_VARARGS,
- "prepare(conn) -> currently does nothing"},
+ /* {"prepare", (PyCFunction)binary_prepare, METH_VARARGS,
+ "prepare(conn) -> currently does nothing"},*/
{NULL} /* Sentinel */
};
diff --git a/psycopg/adapter_datetime.c b/psycopg/adapter_datetime.c
index 36051b5..2f3b70a 100644
--- a/psycopg/adapter_datetime.c
+++ b/psycopg/adapter_datetime.c
@@ -108,8 +108,8 @@ static struct PyMemberDef pydatetimeObject_members[] = {
static PyMethodDef pydatetimeObject_methods[] = {
{"getquoted", (PyCFunction)pydatetime_getquoted, METH_VARARGS,
"getquoted() -> wrapped object value as SQL date/time"},
- {"prepare", (PyCFunction)pydatetime_prepare, METH_VARARGS,
- "prepare(conn) -> currently does nothing"},
+ /* {"prepare", (PyCFunction)pydatetime_prepare, METH_VARARGS,
+ "prepare(conn) -> currently does nothing"}, */
{NULL} /* Sentinel */
};
diff --git a/psycopg/adapter_mxdatetime.c b/psycopg/adapter_mxdatetime.c
index 6b4e0c3..1c83e0c 100644
--- a/psycopg/adapter_mxdatetime.c
+++ b/psycopg/adapter_mxdatetime.c
@@ -84,8 +84,8 @@ static struct PyMemberDef mxdatetimeObject_members[] = {
static PyMethodDef mxdatetimeObject_methods[] = {
{"getquoted", (PyCFunction)mxdatetime_getquoted, METH_VARARGS,
"getquoted() -> wrapped object value as SQL date/time"},
- {"prepare", (PyCFunction)mxdatetime_prepare, METH_VARARGS,
- "prepare(conn) -> currently does nothing"},
+ /* {"prepare", (PyCFunction)mxdatetime_prepare, METH_VARARGS,
+ "prepare(conn) -> currently does nothing"}, */
{NULL} /* Sentinel */
};
diff --git a/psycopg/adapter_pboolean.c b/psycopg/adapter_pboolean.c
index 268c938..a58aecd 100644
--- a/psycopg/adapter_pboolean.c
+++ b/psycopg/adapter_pboolean.c
@@ -76,8 +76,8 @@ static struct PyMemberDef pbooleanObject_members[] = {
static PyMethodDef pbooleanObject_methods[] = {
{"getquoted", (PyCFunction)pboolean_getquoted, METH_VARARGS,
"getquoted() -> wrapped object value as SQL-quoted string"},
- {"prepare", (PyCFunction)pboolean_prepare, METH_VARARGS,
- "prepare(conn) -> currently does nothing"},
+ /* {"prepare", (PyCFunction)pboolean_prepare, METH_VARARGS,
+ "prepare(conn) -> currently does nothing"}, */
{NULL} /* Sentinel */
};
diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c
index 341f275..330b6d8 100644
--- a/psycopg/cursor_type.c
+++ b/psycopg/cursor_type.c
@@ -61,6 +61,38 @@ psyco_curs_close(cursorObject *self, PyObject *args)
/* mogrify a query string and build argument array or dict */
+static PyObject*
+_mogrify_getquoted(PyObject *obj, connectionObject *conn)
+{
+ PyObject *res = NULL;
+ PyObject *tmp = microprotocols_adapt(
+ obj, (PyObject*)&isqlquoteType, NULL);
+
+ if (tmp != NULL) {
+ Dprintf("_mogrify: adapted to %s", tmp->ob_type->tp_name);
+
+ /* if requested prepare the object passing it the connection */
+ if (PyObject_HasAttrString(tmp, "prepare")) {
+ res = PyObject_CallMethod(tmp, "prepare", "O", (PyObject*)conn);
+ if (res == NULL) {
+ Py_DECREF(tmp);
+ return NULL;
+ }
+ else {
+ Py_DECREF(res);
+ }
+ }
+
+ /* call the getquoted method on tmp (that should exist because we
+ adapted to the right protocol) */
+ res = PyObject_CallMethod(tmp, "getquoted", NULL);
+ Py_DECREF(tmp);
+ }
+
+ /* we return res with one extra reference, the caller shall free it */
+ return res;
+}
+
static int
_mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
{
@@ -131,28 +163,17 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
if (*d) *d = 's';
}
else {
- t = microprotocols_adapt(value,
- (PyObject*)&isqlquoteType,
- NULL);
- if (t != NULL) {
- /* t is a new object, refcnt = 1 */
- Dprintf("_mogrify: adapted to %s",
- t->ob_type->tp_name);
-
- /* prepare the object passing it the connection */
- PyObject_CallMethod(t, "prepare", "O",
- (PyObject*)conn);
+ t = _mogrify_getquoted(value, conn);
+ if (t != NULL) {
PyDict_SetItem(n, key, t);
/* both key and t refcnt +1, key is at 2 now */
}
else {
- /* we did not found an adapter but we don't raise
- an exception; just pass the original value */
- PyErr_Clear();
- PyDict_SetItem(n, key, value);
- Dprintf("_mogrify: set value refcnt: %d",
- value->ob_refcnt);
+ /* no adapter found, raise a BIG exception */
+ Py_XDECREF(value);
+ Py_DECREF(n);
+ return -1;
}
}
@@ -200,20 +221,16 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
Py_DECREF(value);
}
else {
- PyObject *t = microprotocols_adapt(value,
- (PyObject*)&isqlquoteType,
- NULL);
- if (t != NULL) {
- /* prepare the object passing it the connection */
- PyObject_CallMethod(t, "prepare", "O", (PyObject*)conn);
+ PyObject *t = _mogrify_getquoted(value, conn);
+ if (t != NULL) {
PyTuple_SET_ITEM(n, index, t);
Py_DECREF(value);
}
else {
- PyErr_Clear();
- PyTuple_SET_ITEM(n, index, value);
- /* here we steal value ref, no need to DECREF */
+ Py_DECREF(n);
+ Py_DECREF(value);
+ return -1;
}
}
c = d;
@@ -228,7 +245,7 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
n = PyTuple_New(0);
*new = n;
- return 0;;
+ return 0;
}
#define psyco_curs_execute_doc \
diff --git a/psycopg/microprotocols.c b/psycopg/microprotocols.c
index c9c2af8..9675d91 100644
--- a/psycopg/microprotocols.c
+++ b/psycopg/microprotocols.c
@@ -58,8 +58,7 @@ microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast)
{
if (proto == NULL) proto = (PyObject*)&isqlquoteType;
- Dprintf("microprotocols_add: cast %p for (%s, ?)",
- cast, type->tp_name);
+ Dprintf("microprotocols_add: cast %p for (%s, ?)", cast, type->tp_name);
PyDict_SetItem(psyco_adapters,
Py_BuildValue("(OO)", (PyObject*)type, proto),
@@ -78,6 +77,8 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
because the ISQLQuote type is abstract and there is no way to get a
quotable object to be its instance */
+ Dprintf("microprotocols_adapt: trying to adapt %s", obj->ob_type->tp_name);
+
/* look for an adapter in the registry */
key = Py_BuildValue("(OO)", (PyObject*)obj->ob_type, proto);
adapter = PyDict_GetItem(psyco_adapters, key);
@@ -95,14 +96,14 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
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__")) {
- PyObject *adapted = PyObject_CallMethod(proto, "__conform__","O", obj);
+ PyObject *adapted = PyObject_CallMethod(obj, "__conform__","O", proto);
if (adapted && adapted != Py_None) return adapted;
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError))
return NULL;
}
-
+
/* else set the right exception and return NULL */
PyErr_SetString(ProgrammingError, "can't adapt");
return NULL;
diff --git a/psycopg/microprotocols_proto.c b/psycopg/microprotocols_proto.c
index 31cd4cd..861c8ef 100644
--- a/psycopg/microprotocols_proto.c
+++ b/psycopg/microprotocols_proto.c
@@ -106,8 +106,8 @@ static struct PyMethodDef isqlquoteObject_methods[] = {
METH_VARARGS, psyco_isqlquote_getbinary_doc},
{"getbuffer", (PyCFunction)psyco_isqlquote_getbuffer,
METH_VARARGS, psyco_isqlquote_getbuffer_doc},
- {"prepare", (PyCFunction)psyco_isqlquote_prepare,
- METH_VARARGS, psyco_isqlquote_prepare_doc},
+ /* {"prepare", (PyCFunction)psyco_isqlquote_prepare,
+ METH_VARARGS, psyco_isqlquote_prepare_doc}, */
{NULL}
};
diff --git a/psycopg/psycopgmodule.c b/psycopg/psycopgmodule.c
index 0d9e40d..da2109d 100644
--- a/psycopg/psycopgmodule.c
+++ b/psycopg/psycopgmodule.c
@@ -34,6 +34,7 @@
#include "psycopg/adapter_qstring.h"
#include "psycopg/adapter_binary.h"
#include "psycopg/adapter_pboolean.h"
+#include "psycopg/adapter_asis.h"
#ifdef HAVE_MXDATETIME
@@ -187,6 +188,10 @@ psyco_adapters_init(PyObject *mod)
{
PyObject *call;
+ microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&asisType);
+ microprotocols_add(&PyInt_Type, NULL, (PyObject*)&asisType);
+ microprotocols_add(&PyLong_Type, NULL, (PyObject*)&asisType);
+
microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType);
microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType);
microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType);
@@ -225,6 +230,9 @@ static encodingPair encodings[] = {
{"SQL_ASCII", "ascii"},
{"LATIN1", "latin_1"},
{"UNICODE", "utf_8"},
+ /* some compatibility stuff */
+ {"latin-1", "latin_1"},
+
{NULL, NULL}
};
static void psyco_encodings_fill(PyObject *dict)
@@ -328,7 +336,9 @@ static PyMethodDef psycopgMethods[] = {
METH_VARARGS, psyco_register_type_doc},
{"new_type", (PyCFunction)typecast_from_python,
METH_VARARGS|METH_KEYWORDS},
-
+
+ {"AsIs", (PyCFunction)psyco_AsIs,
+ METH_VARARGS, psyco_AsIs_doc},
{"QuotedString", (PyCFunction)psyco_QuotedString,
METH_VARARGS, psyco_QuotedString_doc},
{"Boolean", (PyCFunction)psyco_Boolean,
@@ -388,8 +398,9 @@ init_psycopg(void)
cursorType.ob_type = &PyType_Type;
typecastType.ob_type = &PyType_Type;
qstringType.ob_type = &PyType_Type;
- binaryType.ob_type = &PyType_Type;
- isqlquoteType.ob_type = &PyType_Type;
+ binaryType.ob_type = &PyType_Type;
+ isqlquoteType.ob_type = &PyType_Type;
+ asisType.ob_type = &PyType_Type;
if (PyType_Ready(&connectionType) == -1) return;
if (PyType_Ready(&cursorType) == -1) return;
@@ -397,6 +408,7 @@ init_psycopg(void)
if (PyType_Ready(&qstringType) == -1) return;
if (PyType_Ready(&binaryType) == -1) return;
if (PyType_Ready(&isqlquoteType) == -1) return;
+ if (PyType_Ready(&asisType) == -1) return;
#ifdef HAVE_PYBOOL
pbooleanType.ob_type = &PyType_Type;