1 /* row.c - an enhanced tuple for database rows
2 *
3 * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
4 *
5 * This file is part of pysqlite.
6 *
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.
10 *
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:
14 *
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.
22 */
23
24 #ifndef Py_BUILD_CORE_BUILTIN
25 # define Py_BUILD_CORE_MODULE 1
26 #endif
27
28 #include "row.h"
29 #include "cursor.h"
30
31 #define clinic_state() (pysqlite_get_state_by_type(type))
32 #include "clinic/row.c.h"
33 #undef clinic_state
34
35 /*[clinic input]
36 module _sqlite3
37 class _sqlite3.Row "pysqlite_Row *" "clinic_state()->RowType"
38 [clinic start generated code]*/
39 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=966c53403d7f3a40]*/
40
41 static int
row_clear(pysqlite_Row * self)42 row_clear(pysqlite_Row *self)
43 {
44 Py_CLEAR(self->data);
45 Py_CLEAR(self->description);
46 return 0;
47 }
48
49 static int
row_traverse(pysqlite_Row * self,visitproc visit,void * arg)50 row_traverse(pysqlite_Row *self, visitproc visit, void *arg)
51 {
52 Py_VISIT(Py_TYPE(self));
53 Py_VISIT(self->data);
54 Py_VISIT(self->description);
55 return 0;
56 }
57
58 static void
pysqlite_row_dealloc(PyObject * self)59 pysqlite_row_dealloc(PyObject *self)
60 {
61 PyTypeObject *tp = Py_TYPE(self);
62 PyObject_GC_UnTrack(self);
63 tp->tp_clear(self);
64 tp->tp_free(self);
65 Py_DECREF(tp);
66 }
67
68 /*[clinic input]
69 @classmethod
70 _sqlite3.Row.__new__ as pysqlite_row_new
71
72 cursor: object(type='pysqlite_Cursor *', subclass_of='clinic_state()->CursorType')
73 data: object(subclass_of='&PyTuple_Type')
74 /
75
76 [clinic start generated code]*/
77
78 static PyObject *
pysqlite_row_new_impl(PyTypeObject * type,pysqlite_Cursor * cursor,PyObject * data)79 pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor,
80 PyObject *data)
81 /*[clinic end generated code: output=10d58b09a819a4c1 input=b9e954ca31345dbf]*/
82 {
83 pysqlite_Row *self;
84
85 assert(type != NULL && type->tp_alloc != NULL);
86
87 self = (pysqlite_Row *) type->tp_alloc(type, 0);
88 if (self == NULL)
89 return NULL;
90
91 self->data = Py_NewRef(data);
92 self->description = Py_NewRef(cursor->description);
93
94 return (PyObject *) self;
95 }
96
pysqlite_row_item(pysqlite_Row * self,Py_ssize_t idx)97 PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx)
98 {
99 PyObject *item = PyTuple_GetItem(self->data, idx);
100 return Py_XNewRef(item);
101 }
102
103 static int
equal_ignore_case(PyObject * left,PyObject * right)104 equal_ignore_case(PyObject *left, PyObject *right)
105 {
106 int eq = PyObject_RichCompareBool(left, right, Py_EQ);
107 if (eq) { /* equal or error */
108 return eq;
109 }
110 if (!PyUnicode_Check(left) || !PyUnicode_Check(right)) {
111 return 0;
112 }
113 if (!PyUnicode_IS_ASCII(left) || !PyUnicode_IS_ASCII(right)) {
114 return 0;
115 }
116
117 Py_ssize_t len = PyUnicode_GET_LENGTH(left);
118 if (PyUnicode_GET_LENGTH(right) != len) {
119 return 0;
120 }
121 const Py_UCS1 *p1 = PyUnicode_1BYTE_DATA(left);
122 const Py_UCS1 *p2 = PyUnicode_1BYTE_DATA(right);
123 for (; len; len--, p1++, p2++) {
124 if (Py_TOLOWER(*p1) != Py_TOLOWER(*p2)) {
125 return 0;
126 }
127 }
128 return 1;
129 }
130
131 static PyObject *
pysqlite_row_subscript(pysqlite_Row * self,PyObject * idx)132 pysqlite_row_subscript(pysqlite_Row *self, PyObject *idx)
133 {
134 Py_ssize_t _idx;
135 Py_ssize_t nitems, i;
136
137 if (PyLong_Check(idx)) {
138 _idx = PyNumber_AsSsize_t(idx, PyExc_IndexError);
139 if (_idx == -1 && PyErr_Occurred())
140 return NULL;
141 if (_idx < 0)
142 _idx += PyTuple_GET_SIZE(self->data);
143
144 PyObject *item = PyTuple_GetItem(self->data, _idx);
145 return Py_XNewRef(item);
146 } else if (PyUnicode_Check(idx)) {
147 nitems = PyTuple_Size(self->description);
148
149 for (i = 0; i < nitems; i++) {
150 PyObject *obj;
151 obj = PyTuple_GET_ITEM(self->description, i);
152 obj = PyTuple_GET_ITEM(obj, 0);
153 int eq = equal_ignore_case(idx, obj);
154 if (eq < 0) {
155 return NULL;
156 }
157 if (eq) {
158 /* found item */
159 PyObject *item = PyTuple_GetItem(self->data, i);
160 return Py_XNewRef(item);
161 }
162 }
163
164 PyErr_SetString(PyExc_IndexError, "No item with that key");
165 return NULL;
166 }
167 else if (PySlice_Check(idx)) {
168 return PyObject_GetItem(self->data, idx);
169 }
170 else {
171 PyErr_SetString(PyExc_IndexError, "Index must be int or string");
172 return NULL;
173 }
174 }
175
176 static Py_ssize_t
pysqlite_row_length(pysqlite_Row * self)177 pysqlite_row_length(pysqlite_Row* self)
178 {
179 return PyTuple_GET_SIZE(self->data);
180 }
181
182 /*[clinic input]
183 _sqlite3.Row.keys as pysqlite_row_keys
184
185 Returns the keys of the row.
186 [clinic start generated code]*/
187
188 static PyObject *
pysqlite_row_keys_impl(pysqlite_Row * self)189 pysqlite_row_keys_impl(pysqlite_Row *self)
190 /*[clinic end generated code: output=efe3dfb3af6edc07 input=7549a122827c5563]*/
191 {
192 PyObject* list;
193 Py_ssize_t nitems, i;
194
195 list = PyList_New(0);
196 if (!list) {
197 return NULL;
198 }
199 nitems = PyTuple_Size(self->description);
200
201 for (i = 0; i < nitems; i++) {
202 if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) {
203 Py_DECREF(list);
204 return NULL;
205 }
206 }
207
208 return list;
209 }
210
pysqlite_iter(pysqlite_Row * self)211 static PyObject* pysqlite_iter(pysqlite_Row* self)
212 {
213 return PyObject_GetIter(self->data);
214 }
215
pysqlite_row_hash(pysqlite_Row * self)216 static Py_hash_t pysqlite_row_hash(pysqlite_Row *self)
217 {
218 return PyObject_Hash(self->description) ^ PyObject_Hash(self->data);
219 }
220
pysqlite_row_richcompare(pysqlite_Row * self,PyObject * _other,int opid)221 static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
222 {
223 if (opid != Py_EQ && opid != Py_NE)
224 Py_RETURN_NOTIMPLEMENTED;
225
226 pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self));
227 if (PyObject_TypeCheck(_other, state->RowType)) {
228 pysqlite_Row *other = (pysqlite_Row *)_other;
229 int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
230 if (eq < 0) {
231 return NULL;
232 }
233 if (eq) {
234 return PyObject_RichCompare(self->data, other->data, opid);
235 }
236 return PyBool_FromLong(opid != Py_EQ);
237 }
238 Py_RETURN_NOTIMPLEMENTED;
239 }
240
241 static PyMethodDef row_methods[] = {
242 PYSQLITE_ROW_KEYS_METHODDEF
243 {NULL, NULL}
244 };
245
246 static PyType_Slot row_slots[] = {
247 {Py_tp_dealloc, pysqlite_row_dealloc},
248 {Py_tp_hash, pysqlite_row_hash},
249 {Py_tp_methods, row_methods},
250 {Py_tp_richcompare, pysqlite_row_richcompare},
251 {Py_tp_iter, pysqlite_iter},
252 {Py_mp_length, pysqlite_row_length},
253 {Py_mp_subscript, pysqlite_row_subscript},
254 {Py_sq_length, pysqlite_row_length},
255 {Py_sq_item, pysqlite_row_item},
256 {Py_tp_new, pysqlite_row_new},
257 {Py_tp_traverse, row_traverse},
258 {Py_tp_clear, row_clear},
259 {0, NULL},
260 };
261
262 static PyType_Spec row_spec = {
263 .name = MODULE_NAME ".Row",
264 .basicsize = sizeof(pysqlite_Row),
265 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
266 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
267 .slots = row_slots,
268 };
269
270 int
pysqlite_row_setup_types(PyObject * module)271 pysqlite_row_setup_types(PyObject *module)
272 {
273 PyObject *type = PyType_FromModuleAndSpec(module, &row_spec, NULL);
274 if (type == NULL) {
275 return -1;
276 }
277 pysqlite_state *state = pysqlite_get_state(module);
278 state->RowType = (PyTypeObject *)type;
279 return 0;
280 }
281