1 /* adapter_list.c - python list objects
3 * Copyright (C) 2004-2005 Federico Di Gregorio <fog@debian.org>
5 * This file is part of psycopg.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include <structmember.h>
24 #include <stringobject.h>
26 #define PSYCOPG_MODULE
27 #include "psycopg/config.h"
28 #include "psycopg/python.h"
29 #include "psycopg/psycopg.h"
30 #include "psycopg/adapter_list.h"
31 #include "psycopg/microprotocols.h"
32 #include "psycopg/microprotocols_proto.h"
35 /* list_str, list_getquoted - return result of quoting */
38 list_quote(listObject *self)
40 /* adapt the list by calling adapt() recursively and then wrapping
41 everything into "ARRAY[]" */
42 PyObject *tmp = NULL, *str = NULL, *joined = NULL, *res = NULL;
45 len = PyList_GET_SIZE(self->wrapped);
47 /* empty arrays are converted to NULLs (still searching for a way to
48 insert an empty array in postgresql */
49 if (len == 0) return PyString_FromString("'{}'");
51 tmp = PyTuple_New(len);
53 for (i=0; i<len; i++) {
55 microprotocol_getquoted(PyList_GET_ITEM(self->wrapped, i),
56 (connectionObject*)self->connection);
57 if (quoted == NULL) goto error;
59 /* here we don't loose a refcnt: SET_ITEM does not change the
60 reference count and we are just transferring ownership of the tmp
61 object to the tuple */
62 PyTuple_SET_ITEM(tmp, i, quoted);
65 /* now that we have a tuple of adapted objects we just need to join them
66 and put "ARRAY[] around the result */
67 str = PyString_FromString(", ");
68 joined = PyObject_CallMethod(str, "join", "(O)", tmp);
69 if (joined == NULL) goto error;
71 res = PyString_FromFormat("ARRAY[%s]", PyString_AsString(joined));
81 list_str(listObject *self, PyObject *args)
83 if (!PyArg_ParseTuple(args, "")) return NULL;
84 return list_quote(self);
88 list_getquoted(listObject *self, PyObject *args)
90 if (!PyArg_ParseTuple(args, "")) return NULL;
91 return list_quote(self);
95 list_prepare(listObject *self, PyObject *args)
97 connectionObject *conn;
99 if (!PyArg_ParseTuple(args, "O", &conn))
102 /* note that we don't copy the encoding from the connection, but take a
103 reference to it; we'll need it during the recursive adapt() call (the
104 encoding is here for a future expansion that will make .getquoted()
105 work even without a connection to the backend. */
106 Py_XDECREF(self->connection);
107 self->connection = (PyObject*)conn;
108 Py_INCREF(self->connection);
115 list_conform(listObject *self, PyObject *args)
117 PyObject *res, *proto;
119 if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
121 if (proto == (PyObject*)&isqlquoteType)
122 res = (PyObject*)self;
130 /** the DateTime wrapper object **/
132 /* object member list */
134 static struct PyMemberDef listObject_members[] = {
135 {"adapted", T_OBJECT, offsetof(listObject, wrapped), RO},
139 /* object method table */
141 static PyMethodDef listObject_methods[] = {
142 {"getquoted", (PyCFunction)list_getquoted, METH_VARARGS,
143 "getquoted() -> wrapped object value as SQL date/time"},
144 {"prepare", (PyCFunction)list_prepare, METH_VARARGS,
145 "prepare(conn) -> set encoding to conn->encoding"},
146 {"__conform__", (PyCFunction)list_conform, METH_VARARGS, NULL},
147 {NULL} /* Sentinel */
150 /* initialization and finalization methods */
153 list_setup(listObject *self, PyObject *obj, char *enc)
155 Dprintf("list_setup: init list object at %p, refcnt = %d",
156 self, ((PyObject *)self)->ob_refcnt);
158 if (!PyList_Check(obj))
161 /* FIXME: remove this orrible strdup */
162 if (enc) self->encoding = strdup(enc);
164 self->connection = NULL;
166 Py_INCREF(self->wrapped);
168 Dprintf("list_setup: good list object at %p, refcnt = %d",
169 self, ((PyObject *)self)->ob_refcnt);
174 list_dealloc(PyObject* obj)
176 listObject *self = (listObject *)obj;
178 Py_XDECREF(self->wrapped);
179 Py_XDECREF(self->connection);
180 if (self->encoding) free(self->encoding);
182 Dprintf("list_dealloc: deleted list object at %p, "
183 "refcnt = %d", obj, obj->ob_refcnt);
185 obj->ob_type->tp_free(obj);
189 list_init(PyObject *obj, PyObject *args, PyObject *kwds)
192 char *enc = "latin-1"; /* default encoding as in Python */
194 if (!PyArg_ParseTuple(args, "O|s", &l, &enc))
197 return list_setup((listObject *)obj, l, enc);
201 list_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
203 return type->tp_alloc(type, 0);
207 list_del(PyObject* self)
213 list_repr(listObject *self)
215 return PyString_FromFormat("<psycopg2._psycopg.List object at %p>", self);
220 #define listType_doc \
221 "List(list) -> new list wrapper object"
223 PyTypeObject listType = {
224 PyObject_HEAD_INIT(NULL)
226 "psycopg2._psycopg.List",
229 list_dealloc, /*tp_dealloc*/
235 (reprfunc)list_repr, /*tp_repr*/
237 0, /*tp_as_sequence*/
242 (reprfunc)list_str, /*tp_str*/
247 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
249 listType_doc, /*tp_doc*/
254 0, /*tp_richcompare*/
255 0, /*tp_weaklistoffset*/
260 /* Attribute descriptor and subclassing stuff */
262 listObject_methods, /*tp_methods*/
263 listObject_members, /*tp_members*/
272 list_init, /*tp_init*/
273 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
275 (freefunc)list_del, /*tp_free Low-level free-memory routine */
276 0, /*tp_is_gc For PyObject_IS_GC */
278 0, /*tp_mro method resolution order */
285 /** module-level functions **/
288 psyco_List(PyObject *module, PyObject *args)
291 char *enc = "latin-1"; /* default encoding as in Python */
293 if (!PyArg_ParseTuple(args, "O|s", &str, &enc))
296 return PyObject_CallFunction((PyObject *)&listType, "Os", str, enc);