Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(9)

Delta Between Two Patch Sets: Modules/_sqlite/row.c

Issue 13583: sqlite3.Row doesn't support slice indexes
Left Patch Set: Created 8 years, 2 months ago
Right Patch Set: Created 4 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/sqlite3/test/factory.py ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* row.c - an enhanced tuple for database rows 1 /* row.c - an enhanced tuple for database rows
2 * 2 *
3 * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de> 3 * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
4 * 4 *
5 * This file is part of pysqlite. 5 * This file is part of pysqlite.
6 * 6 *
7 * This software is provided 'as-is', without any express or implied 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 8 * warranty. In no event will the authors be held liable for any damages
9 * arising from the use of this software. 9 * arising from the use of this software.
10 * 10 *
11 * Permission is granted to anyone to use this software for any purpose, 11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it 12 * including commercial applications, and to alter it and redistribute it
13 * freely, subject to the following restrictions: 13 * freely, subject to the following restrictions:
14 * 14 *
15 * 1. The origin of this software must not be misrepresented; you must not 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 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 17 * in a product, an acknowledgment in the product documentation would be
18 * appreciated but is not required. 18 * appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be 19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software. 20 * misrepresented as being the original software.
21 * 3. This notice may not be removed or altered from any source distribution. 21 * 3. This notice may not be removed or altered from any source distribution.
22 */ 22 */
23 23
24 #include "row.h" 24 #include "row.h"
25 #include "cursor.h" 25 #include "cursor.h"
26 #include "sqlitecompat.h"
27 26
28 void pysqlite_row_dealloc(pysqlite_Row* self) 27 void pysqlite_row_dealloc(pysqlite_Row* self)
29 { 28 {
30 Py_XDECREF(self->data); 29 Py_XDECREF(self->data);
31 Py_XDECREF(self->description); 30 Py_XDECREF(self->description);
32 31
33 Py_TYPE(self)->tp_free((PyObject*)self); 32 Py_TYPE(self)->tp_free((PyObject*)self);
34 } 33 }
35 34
36 int pysqlite_row_init(pysqlite_Row* self, PyObject* args, PyObject* kwargs) 35 static PyObject *
37 { 36 pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
37 {
38 pysqlite_Row *self;
38 PyObject* data; 39 PyObject* data;
39 pysqlite_Cursor* cursor; 40 pysqlite_Cursor* cursor;
40 41
41 self->data = 0; 42 assert(type != NULL && type->tp_alloc != NULL);
42 self->description = 0; 43
43 44 if (!_PyArg_NoKeywords("Row()", kwargs))
44 if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) { 45 return NULL;
45 return -1; 46 if (!PyArg_ParseTuple(args, "OO", &cursor, &data))
46 } 47 return NULL;
47 48
48 if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType) ) { 49 if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType) ) {
49 PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); 50 PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument");
50 return -1; 51 return NULL;
51 } 52 }
52 53
53 if (!PyTuple_Check(data)) { 54 if (!PyTuple_Check(data)) {
54 PyErr_SetString(PyExc_TypeError, "tuple required for second argument"); 55 PyErr_SetString(PyExc_TypeError, "tuple required for second argument");
55 return -1; 56 return NULL;
56 } 57 }
58
59 self = (pysqlite_Row *) type->tp_alloc(type, 0);
60 if (self == NULL)
61 return NULL;
57 62
58 Py_INCREF(data); 63 Py_INCREF(data);
59 self->data = data; 64 self->data = data;
60 65
61 Py_INCREF(cursor->description); 66 Py_INCREF(cursor->description);
62 self->description = cursor->description; 67 self->description = cursor->description;
63 68
64 return 0; 69 return (PyObject *) self;
70 }
71
72 PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx)
73 {
74 PyObject* item = PyTuple_GetItem(self->data, idx);
75 Py_XINCREF(item);
76 return item;
65 } 77 }
66 78
67 PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) 79 PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx)
68 { 80 {
69 long _idx; 81 Py_ssize_t _idx;
70 char* key; 82 char* key;
71 int nitems, i; 83 Py_ssize_t nitems, i;
72 char* compare_key; 84 char* compare_key;
73 85
74 char* p1; 86 char* p1;
75 char* p2; 87 char* p2;
76 88
77 PyObject* item; 89 PyObject* item;
78 90
79 if (PyInt_Check(idx)) { 91 if (PyLong_Check(idx)) {
80 _idx = PyInt_AsLong(idx); 92 _idx = PyNumber_AsSsize_t(idx, PyExc_IndexError);
93 if (_idx == -1 && PyErr_Occurred())
94 return NULL;
95 if (_idx < 0)
96 _idx += PyTuple_GET_SIZE(self->data);
81 item = PyTuple_GetItem(self->data, _idx); 97 item = PyTuple_GetItem(self->data, _idx);
82 Py_XINCREF(item); 98 Py_XINCREF(item);
83 return item; 99 return item;
84 } else if (PyLong_Check(idx)) { 100 } else if (PyUnicode_Check(idx)) {
85 _idx = PyLong_AsLong(idx); 101 key = _PyUnicode_AsString(idx);
86 item = PyTuple_GetItem(self->data, _idx); 102 if (key == NULL)
87 Py_XINCREF(item); 103 return NULL;
88 return item;
89 } else if (PyString_Check(idx)) {
90 key = PyString_AsString(idx);
91 104
92 nitems = PyTuple_Size(self->description); 105 nitems = PyTuple_Size(self->description);
93 106
94 for (i = 0; i < nitems; i++) { 107 for (i = 0; i < nitems; i++) {
95 compare_key = PyString_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(se lf->description, i), 0)); 108 PyObject *obj;
109 obj = PyTuple_GET_ITEM(self->description, i);
110 obj = PyTuple_GET_ITEM(obj, 0);
111 compare_key = _PyUnicode_AsString(obj);
96 if (!compare_key) { 112 if (!compare_key) {
97 return NULL; 113 return NULL;
98 } 114 }
99 115
100 p1 = key; 116 p1 = key;
101 p2 = compare_key; 117 p2 = compare_key;
102 118
103 while (1) { 119 while (1) {
104 if ((*p1 == (char)0) || (*p2 == (char)0)) { 120 if ((*p1 == (char)0) || (*p2 == (char)0)) {
105 break; 121 break;
(...skipping 11 matching lines...) Expand all
117 /* found item */ 133 /* found item */
118 item = PyTuple_GetItem(self->data, i); 134 item = PyTuple_GetItem(self->data, i);
119 Py_INCREF(item); 135 Py_INCREF(item);
120 return item; 136 return item;
121 } 137 }
122 138
123 } 139 }
124 140
125 PyErr_SetString(PyExc_IndexError, "No item with that key"); 141 PyErr_SetString(PyExc_IndexError, "No item with that key");
126 return NULL; 142 return NULL;
127 } else if (PySlice_Check(idx)) { 143 }
128 Py_ssize_t start, stop, step, slicelength; 144 else if (PySlice_Check(idx)) {
129 if (PySlice_GetIndicesEx((PySliceObject*)idx, 145 return PyObject_GetItem(self->data, idx);
130 PyTuple_GET_SIZE(self->data), 146 }
131 &start, &stop, &step, &slicelength) < 0) { 147 else {
132 return NULL;
133 }
134 return PyTuple_GetSlice(self->data, start, stop);
135 } else {
136 PyErr_SetString(PyExc_IndexError, "Index must be int or string"); 148 PyErr_SetString(PyExc_IndexError, "Index must be int or string");
137 return NULL; 149 return NULL;
138 } 150 }
139 } 151 }
140 152
141 Py_ssize_t pysqlite_row_length(pysqlite_Row* self, PyObject* args, PyObject* kwa rgs) 153 Py_ssize_t pysqlite_row_length(pysqlite_Row* self, PyObject* args, PyObject* kwa rgs)
142 { 154 {
143 return PyTuple_GET_SIZE(self->data); 155 return PyTuple_GET_SIZE(self->data);
144 } 156 }
145 157
146 PyObject* pysqlite_row_keys(pysqlite_Row* self, PyObject* args, PyObject* kwargs ) 158 PyObject* pysqlite_row_keys(pysqlite_Row* self, PyObject* args, PyObject* kwargs )
147 { 159 {
148 PyObject* list; 160 PyObject* list;
149 int nitems, i; 161 Py_ssize_t nitems, i;
150 162
151 list = PyList_New(0); 163 list = PyList_New(0);
152 if (!list) { 164 if (!list) {
153 return NULL; 165 return NULL;
154 } 166 }
155 nitems = PyTuple_Size(self->description); 167 nitems = PyTuple_Size(self->description);
156 168
157 for (i = 0; i < nitems; i++) { 169 for (i = 0; i < nitems; i++) {
158 if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->descript ion, i), 0)) != 0) { 170 if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->descript ion, i), 0)) != 0) {
159 Py_DECREF(list); 171 Py_DECREF(list);
160 return NULL; 172 return NULL;
161 } 173 }
162 } 174 }
163 175
164 return list; 176 return list;
165 } 177 }
166 178
167 static int pysqlite_row_print(pysqlite_Row* self, FILE *fp, int flags) 179 static int pysqlite_row_print(pysqlite_Row* self, FILE *fp, int flags)
168 { 180 {
169 return (&PyTuple_Type)->tp_print(self->data, fp, flags); 181 return (&PyTuple_Type)->tp_print(self->data, fp, flags);
170 } 182 }
171 183
172 static PyObject* pysqlite_iter(pysqlite_Row* self) 184 static PyObject* pysqlite_iter(pysqlite_Row* self)
173 { 185 {
174 return PyObject_GetIter(self->data); 186 return PyObject_GetIter(self->data);
175 } 187 }
176 188
177 static long pysqlite_row_hash(pysqlite_Row *self) 189 static Py_hash_t pysqlite_row_hash(pysqlite_Row *self)
178 { 190 {
179 return PyObject_Hash(self->description) ^ PyObject_Hash(self->data); 191 return PyObject_Hash(self->description) ^ PyObject_Hash(self->data);
180 } 192 }
181 193
182 static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid) 194 static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
183 { 195 {
184 if (opid != Py_EQ && opid != Py_NE) { 196 if (opid != Py_EQ && opid != Py_NE)
185 Py_INCREF(Py_NotImplemented); 197 Py_RETURN_NOTIMPLEMENTED;
186 return Py_NotImplemented; 198
187 }
188 if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) { 199 if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
189 pysqlite_Row *other = (pysqlite_Row *)_other; 200 pysqlite_Row *other = (pysqlite_Row *)_other;
190 PyObject *res = PyObject_RichCompare(self->description, other->descripti on, opid); 201 PyObject *res = PyObject_RichCompare(self->description, other->descripti on, opid);
191 if ((opid == Py_EQ && res == Py_True) 202 if ((opid == Py_EQ && res == Py_True)
192 || (opid == Py_NE && res == Py_False)) { 203 || (opid == Py_NE && res == Py_False)) {
193 Py_DECREF(res); 204 Py_DECREF(res);
194 return PyObject_RichCompare(self->data, other->data, opid); 205 return PyObject_RichCompare(self->data, other->data, opid);
195 } 206 }
196 } 207 }
197 Py_INCREF(Py_NotImplemented); 208 Py_RETURN_NOTIMPLEMENTED;
198 return Py_NotImplemented;
199 } 209 }
200 210
201 PyMappingMethods pysqlite_row_as_mapping = { 211 PyMappingMethods pysqlite_row_as_mapping = {
202 /* mp_length */ (lenfunc)pysqlite_row_length, 212 /* mp_length */ (lenfunc)pysqlite_row_length,
203 /* mp_subscript */ (binaryfunc)pysqlite_row_subscript, 213 /* mp_subscript */ (binaryfunc)pysqlite_row_subscript,
204 /* mp_ass_subscript */ (objobjargproc)0, 214 /* mp_ass_subscript */ (objobjargproc)0,
205 }; 215 };
216
217 static PySequenceMethods pysqlite_row_as_sequence = {
218 /* sq_length */ (lenfunc)pysqlite_row_length,
219 /* sq_concat */ 0,
220 /* sq_repeat */ 0,
221 /* sq_item */ (ssizeargfunc)pysqlite_row_item,
222 };
223
206 224
207 static PyMethodDef pysqlite_row_methods[] = { 225 static PyMethodDef pysqlite_row_methods[] = {
208 {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, 226 {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS,
209 PyDoc_STR("Returns the keys of the row.")}, 227 PyDoc_STR("Returns the keys of the row.")},
210 {NULL, NULL} 228 {NULL, NULL}
211 }; 229 };
212 230
213 231
214 PyTypeObject pysqlite_RowType = { 232 PyTypeObject pysqlite_RowType = {
215 PyVarObject_HEAD_INIT(NULL, 0) 233 PyVarObject_HEAD_INIT(NULL, 0)
216 MODULE_NAME ".Row", /* tp_name */ 234 MODULE_NAME ".Row", /* tp_name */
217 sizeof(pysqlite_Row), /* tp_basicsize */ 235 sizeof(pysqlite_Row), /* tp_basicsize */
218 0, /* tp_itemsize */ 236 0, /* tp_itemsize */
219 (destructor)pysqlite_row_dealloc, /* tp_dealloc */ 237 (destructor)pysqlite_row_dealloc, /* tp_dealloc */
220 (printfunc)pysqlite_row_print, /* tp_print */ 238 (printfunc)pysqlite_row_print, /* tp_print */
221 0, /* tp_getattr */ 239 0, /* tp_getattr */
222 0, /* tp_setattr */ 240 0, /* tp_setattr */
223 0, /* tp_compare */ 241 0, /* tp_reserved */
224 0, /* tp_repr */ 242 0, /* tp_repr */
225 0, /* tp_as_number */ 243 0, /* tp_as_number */
226 0, /* tp_as_sequence */ 244 0, /* tp_as_sequence */
227 0, /* tp_as_mapping */ 245 0, /* tp_as_mapping */
228 (hashfunc)pysqlite_row_hash, /* tp_hash */ 246 (hashfunc)pysqlite_row_hash, /* tp_hash */
229 0, /* tp_call */ 247 0, /* tp_call */
230 0, /* tp_str */ 248 0, /* tp_str */
231 0, /* tp_getattro */ 249 0, /* tp_getattro */
232 0, /* tp_setattro */ 250 0, /* tp_setattro */
233 0, /* tp_as_buffer */ 251 0, /* tp_as_buffer */
234 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 252 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
235 0, /* tp_doc */ 253 0, /* tp_doc */
236 (traverseproc)0, /* tp_traverse */ 254 (traverseproc)0, /* tp_traverse */
237 0, /* tp_clear */ 255 0, /* tp_clear */
238 (richcmpfunc)pysqlite_row_richcompare, /* tp_richcompare */ 256 (richcmpfunc)pysqlite_row_richcompare, /* tp_richcompare */
239 0, /* tp_weaklistoffset */ 257 0, /* tp_weaklistoffset */
240 (getiterfunc)pysqlite_iter, /* tp_iter */ 258 (getiterfunc)pysqlite_iter, /* tp_iter */
241 0, /* tp_iternext */ 259 0, /* tp_iternext */
242 pysqlite_row_methods, /* tp_methods */ 260 pysqlite_row_methods, /* tp_methods */
243 0, /* tp_members */ 261 0, /* tp_members */
244 0, /* tp_getset */ 262 0, /* tp_getset */
245 0, /* tp_base */ 263 0, /* tp_base */
246 0, /* tp_dict */ 264 0, /* tp_dict */
247 0, /* tp_descr_get */ 265 0, /* tp_descr_get */
248 0, /* tp_descr_set */ 266 0, /* tp_descr_set */
249 0, /* tp_dictoffset */ 267 0, /* tp_dictoffset */
250 (initproc)pysqlite_row_init, /* tp_init */ 268 0, /* tp_init */
251 0, /* tp_alloc */ 269 0, /* tp_alloc */
252 0, /* tp_new */ 270 0, /* tp_new */
253 0 /* tp_free */ 271 0 /* tp_free */
254 }; 272 };
255 273
256 extern int pysqlite_row_setup_types(void) 274 extern int pysqlite_row_setup_types(void)
257 { 275 {
258 pysqlite_RowType.tp_new = PyType_GenericNew; 276 pysqlite_RowType.tp_new = pysqlite_row_new;
259 pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping; 277 pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping;
278 pysqlite_RowType.tp_as_sequence = &pysqlite_row_as_sequence;
260 return PyType_Ready(&pysqlite_RowType); 279 return PyType_Ready(&pysqlite_RowType);
261 } 280 }
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+