1 /* row.c - an enhanced tuple for database rows
3 * Copyright (C) 2005-2006 Gerhard Häring <gh@ghaering.de>
5 * This file is part of pysqlite.
7 * This software is provided 'as-is', without any express or implied
8 * warranty. In no event will the authors be held liable for any damages
9 * arising from the use of this software.
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it
13 * freely, subject to the following restrictions:
15 * 1. The origin of this software must not be misrepresented; you must not
16 * claim that you wrote the original software. If you use this software
17 * in a product, an acknowledgment in the product documentation would be
18 * appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software.
21 * 3. This notice may not be removed or altered from any source distribution.
26 #include "sqlitecompat.h"
28 void pysqlite_row_dealloc(pysqlite_Row
* self
)
30 Py_XDECREF(self
->data
);
31 Py_XDECREF(self
->description
);
33 Py_TYPE(self
)->tp_free((PyObject
*)self
);
36 int pysqlite_row_init(pysqlite_Row
* self
, PyObject
* args
, PyObject
* kwargs
)
39 pysqlite_Cursor
* cursor
;
42 self
->description
= 0;
44 if (!PyArg_ParseTuple(args
, "OO", &cursor
, &data
)) {
48 if (!PyObject_IsInstance((PyObject
*)cursor
, (PyObject
*)&pysqlite_CursorType
)) {
49 PyErr_SetString(PyExc_TypeError
, "instance of cursor required for first argument");
53 if (!PyTuple_Check(data
)) {
54 PyErr_SetString(PyExc_TypeError
, "tuple required for second argument");
61 Py_INCREF(cursor
->description
);
62 self
->description
= cursor
->description
;
67 PyObject
* pysqlite_row_subscript(pysqlite_Row
* self
, PyObject
* idx
)
79 if (PyInt_Check(idx
)) {
80 _idx
= PyInt_AsLong(idx
);
81 item
= PyTuple_GetItem(self
->data
, _idx
);
84 } else if (PyLong_Check(idx
)) {
85 _idx
= PyLong_AsLong(idx
);
86 item
= PyTuple_GetItem(self
->data
, _idx
);
89 } else if (PyString_Check(idx
)) {
90 key
= PyString_AsString(idx
);
92 nitems
= PyTuple_Size(self
->description
);
94 for (i
= 0; i
< nitems
; i
++) {
95 compare_key
= PyString_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self
->description
, i
), 0));
104 if ((*p1
== (char)0) || (*p2
== (char)0)) {
108 if ((*p1
| 0x20) != (*p2
| 0x20)) {
116 if ((*p1
== (char)0) && (*p2
== (char)0)) {
118 item
= PyTuple_GetItem(self
->data
, i
);
125 PyErr_SetString(PyExc_IndexError
, "No item with that key");
127 } else if (PySlice_Check(idx
)) {
128 PyErr_SetString(PyExc_ValueError
, "slices not implemented, yet");
131 PyErr_SetString(PyExc_IndexError
, "Index must be int or string");
136 Py_ssize_t
pysqlite_row_length(pysqlite_Row
* self
, PyObject
* args
, PyObject
* kwargs
)
138 return PyTuple_GET_SIZE(self
->data
);
141 PyObject
* pysqlite_row_keys(pysqlite_Row
* self
, PyObject
* args
, PyObject
* kwargs
)
146 list
= PyList_New(0);
150 nitems
= PyTuple_Size(self
->description
);
152 for (i
= 0; i
< nitems
; i
++) {
153 if (PyList_Append(list
, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self
->description
, i
), 0)) != 0) {
162 static int pysqlite_row_print(pysqlite_Row
* self
, FILE *fp
, int flags
)
164 return (&PyTuple_Type
)->tp_print(self
->data
, fp
, flags
);
167 static PyObject
* pysqlite_iter(pysqlite_Row
* self
)
169 return PyObject_GetIter(self
->data
);
172 static long pysqlite_row_hash(pysqlite_Row
*self
)
174 return PyObject_Hash(self
->description
) ^ PyObject_Hash(self
->data
);
177 static PyObject
* pysqlite_row_richcompare(pysqlite_Row
*self
, PyObject
*_other
, int opid
)
179 if (opid
!= Py_EQ
&& opid
!= Py_NE
) {
180 Py_INCREF(Py_NotImplemented
);
181 return Py_NotImplemented
;
183 if (PyType_IsSubtype(Py_TYPE(_other
), &pysqlite_RowType
)) {
184 pysqlite_Row
*other
= (pysqlite_Row
*)_other
;
185 PyObject
*res
= PyObject_RichCompare(self
->description
, other
->description
, opid
);
186 if ((opid
== Py_EQ
&& res
== Py_True
)
187 || (opid
== Py_NE
&& res
== Py_False
)) {
189 return PyObject_RichCompare(self
->data
, other
->data
, opid
);
192 Py_INCREF(Py_NotImplemented
);
193 return Py_NotImplemented
;
196 PyMappingMethods pysqlite_row_as_mapping
= {
197 /* mp_length */ (lenfunc
)pysqlite_row_length
,
198 /* mp_subscript */ (binaryfunc
)pysqlite_row_subscript
,
199 /* mp_ass_subscript */ (objobjargproc
)0,
202 static PyMethodDef pysqlite_row_methods
[] = {
203 {"keys", (PyCFunction
)pysqlite_row_keys
, METH_NOARGS
,
204 PyDoc_STR("Returns the keys of the row.")},
209 PyTypeObject pysqlite_RowType
= {
210 PyVarObject_HEAD_INIT(NULL
, 0)
211 MODULE_NAME
".Row", /* tp_name */
212 sizeof(pysqlite_Row
), /* tp_basicsize */
214 (destructor
)pysqlite_row_dealloc
, /* tp_dealloc */
215 (printfunc
)pysqlite_row_print
, /* tp_print */
220 0, /* tp_as_number */
221 0, /* tp_as_sequence */
222 0, /* tp_as_mapping */
223 (hashfunc
)pysqlite_row_hash
, /* tp_hash */
228 0, /* tp_as_buffer */
229 Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
, /* tp_flags */
231 (traverseproc
)0, /* tp_traverse */
233 (richcmpfunc
)pysqlite_row_richcompare
, /* tp_richcompare */
234 0, /* tp_weaklistoffset */
235 (getiterfunc
)pysqlite_iter
, /* tp_iter */
237 pysqlite_row_methods
, /* tp_methods */
242 0, /* tp_descr_get */
243 0, /* tp_descr_set */
244 0, /* tp_dictoffset */
245 (initproc
)pysqlite_row_init
, /* tp_init */
251 extern int pysqlite_row_setup_types(void)
253 pysqlite_RowType
.tp_new
= PyType_GenericNew
;
254 pysqlite_RowType
.tp_as_mapping
= &pysqlite_row_as_mapping
;
255 return PyType_Ready(&pysqlite_RowType
);