row.c 7.4 KB

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