/Modules/_sqlite/row.c

http://unladen-swallow.googlecode.com/ · C · 256 lines · 195 code · 38 blank · 23 comment · 41 complexity · 186f646c7e98d91dc6b55d3c6ecdfba3 MD5 · raw file

  1. /* row.c - an enhanced tuple for database rows
  2. *
  3. * Copyright (C) 2005-2006 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. #include "row.h"
  24. #include "cursor.h"
  25. #include "sqlitecompat.h"
  26. void pysqlite_row_dealloc(pysqlite_Row* self)
  27. {
  28. Py_XDECREF(self->data);
  29. Py_XDECREF(self->description);
  30. Py_TYPE(self)->tp_free((PyObject*)self);
  31. }
  32. int pysqlite_row_init(pysqlite_Row* self, PyObject* args, PyObject* kwargs)
  33. {
  34. PyObject* data;
  35. pysqlite_Cursor* cursor;
  36. self->data = 0;
  37. self->description = 0;
  38. if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) {
  39. return -1;
  40. }
  41. if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) {
  42. PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument");
  43. return -1;
  44. }
  45. if (!PyTuple_Check(data)) {
  46. PyErr_SetString(PyExc_TypeError, "tuple required for second argument");
  47. return -1;
  48. }
  49. Py_INCREF(data);
  50. self->data = data;
  51. Py_INCREF(cursor->description);
  52. self->description = cursor->description;
  53. return 0;
  54. }
  55. PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx)
  56. {
  57. long _idx;
  58. char* key;
  59. int nitems, i;
  60. char* compare_key;
  61. char* p1;
  62. char* p2;
  63. PyObject* item;
  64. if (PyInt_Check(idx)) {
  65. _idx = PyInt_AsLong(idx);
  66. item = PyTuple_GetItem(self->data, _idx);
  67. Py_XINCREF(item);
  68. return item;
  69. } else if (PyLong_Check(idx)) {
  70. _idx = PyLong_AsLong(idx);
  71. item = PyTuple_GetItem(self->data, _idx);
  72. Py_XINCREF(item);
  73. return item;
  74. } else if (PyString_Check(idx)) {
  75. key = PyString_AsString(idx);
  76. nitems = PyTuple_Size(self->description);
  77. for (i = 0; i < nitems; i++) {
  78. compare_key = PyString_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0));
  79. if (!compare_key) {
  80. return NULL;
  81. }
  82. p1 = key;
  83. p2 = compare_key;
  84. while (1) {
  85. if ((*p1 == (char)0) || (*p2 == (char)0)) {
  86. break;
  87. }
  88. if ((*p1 | 0x20) != (*p2 | 0x20)) {
  89. break;
  90. }
  91. p1++;
  92. p2++;
  93. }
  94. if ((*p1 == (char)0) && (*p2 == (char)0)) {
  95. /* found item */
  96. item = PyTuple_GetItem(self->data, i);
  97. Py_INCREF(item);
  98. return item;
  99. }
  100. }
  101. PyErr_SetString(PyExc_IndexError, "No item with that key");
  102. return NULL;
  103. } else if (PySlice_Check(idx)) {
  104. PyErr_SetString(PyExc_ValueError, "slices not implemented, yet");
  105. return NULL;
  106. } else {
  107. PyErr_SetString(PyExc_IndexError, "Index must be int or string");
  108. return NULL;
  109. }
  110. }
  111. Py_ssize_t pysqlite_row_length(pysqlite_Row* self, PyObject* args, PyObject* kwargs)
  112. {
  113. return PyTuple_GET_SIZE(self->data);
  114. }
  115. PyObject* pysqlite_row_keys(pysqlite_Row* self, PyObject* args, PyObject* kwargs)
  116. {
  117. PyObject* list;
  118. int nitems, i;
  119. list = PyList_New(0);
  120. if (!list) {
  121. return NULL;
  122. }
  123. nitems = PyTuple_Size(self->description);
  124. for (i = 0; i < nitems; i++) {
  125. if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) {
  126. Py_DECREF(list);
  127. return NULL;
  128. }
  129. }
  130. return list;
  131. }
  132. static int pysqlite_row_print(pysqlite_Row* self, FILE *fp, int flags)
  133. {
  134. return (&PyTuple_Type)->tp_print(self->data, fp, flags);
  135. }
  136. static PyObject* pysqlite_iter(pysqlite_Row* self)
  137. {
  138. return PyObject_GetIter(self->data);
  139. }
  140. static long pysqlite_row_hash(pysqlite_Row *self)
  141. {
  142. return PyObject_Hash(self->description) ^ PyObject_Hash(self->data);
  143. }
  144. static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
  145. {
  146. if (opid != Py_EQ && opid != Py_NE) {
  147. Py_INCREF(Py_NotImplemented);
  148. return Py_NotImplemented;
  149. }
  150. if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
  151. pysqlite_Row *other = (pysqlite_Row *)_other;
  152. PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
  153. if ((opid == Py_EQ && res == Py_True)
  154. || (opid == Py_NE && res == Py_False)) {
  155. Py_DECREF(res);
  156. return PyObject_RichCompare(self->data, other->data, opid);
  157. }
  158. }
  159. Py_INCREF(Py_NotImplemented);
  160. return Py_NotImplemented;
  161. }
  162. PyMappingMethods pysqlite_row_as_mapping = {
  163. /* mp_length */ (lenfunc)pysqlite_row_length,
  164. /* mp_subscript */ (binaryfunc)pysqlite_row_subscript,
  165. /* mp_ass_subscript */ (objobjargproc)0,
  166. };
  167. static PyMethodDef pysqlite_row_methods[] = {
  168. {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS,
  169. PyDoc_STR("Returns the keys of the row.")},
  170. {NULL, NULL}
  171. };
  172. PyTypeObject pysqlite_RowType = {
  173. PyVarObject_HEAD_INIT(NULL, 0)
  174. MODULE_NAME ".Row", /* tp_name */
  175. sizeof(pysqlite_Row), /* tp_basicsize */
  176. 0, /* tp_itemsize */
  177. (destructor)pysqlite_row_dealloc, /* tp_dealloc */
  178. (printfunc)pysqlite_row_print, /* tp_print */
  179. 0, /* tp_getattr */
  180. 0, /* tp_setattr */
  181. 0, /* tp_compare */
  182. 0, /* tp_repr */
  183. 0, /* tp_as_number */
  184. 0, /* tp_as_sequence */
  185. 0, /* tp_as_mapping */
  186. (hashfunc)pysqlite_row_hash, /* tp_hash */
  187. 0, /* tp_call */
  188. 0, /* tp_str */
  189. 0, /* tp_getattro */
  190. 0, /* tp_setattro */
  191. 0, /* tp_as_buffer */
  192. Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
  193. 0, /* tp_doc */
  194. (traverseproc)0, /* tp_traverse */
  195. 0, /* tp_clear */
  196. (richcmpfunc)pysqlite_row_richcompare, /* tp_richcompare */
  197. 0, /* tp_weaklistoffset */
  198. (getiterfunc)pysqlite_iter, /* tp_iter */
  199. 0, /* tp_iternext */
  200. pysqlite_row_methods, /* tp_methods */
  201. 0, /* tp_members */
  202. 0, /* tp_getset */
  203. 0, /* tp_base */
  204. 0, /* tp_dict */
  205. 0, /* tp_descr_get */
  206. 0, /* tp_descr_set */
  207. 0, /* tp_dictoffset */
  208. (initproc)pysqlite_row_init, /* tp_init */
  209. 0, /* tp_alloc */
  210. 0, /* tp_new */
  211. 0 /* tp_free */
  212. };
  213. extern int pysqlite_row_setup_types(void)
  214. {
  215. pysqlite_RowType.tp_new = PyType_GenericNew;
  216. pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping;
  217. return PyType_Ready(&pysqlite_RowType);
  218. }