17db96d56Sopenharmony_ci/* row.c - an enhanced tuple for database rows 27db96d56Sopenharmony_ci * 37db96d56Sopenharmony_ci * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de> 47db96d56Sopenharmony_ci * 57db96d56Sopenharmony_ci * This file is part of pysqlite. 67db96d56Sopenharmony_ci * 77db96d56Sopenharmony_ci * This software is provided 'as-is', without any express or implied 87db96d56Sopenharmony_ci * warranty. In no event will the authors be held liable for any damages 97db96d56Sopenharmony_ci * arising from the use of this software. 107db96d56Sopenharmony_ci * 117db96d56Sopenharmony_ci * Permission is granted to anyone to use this software for any purpose, 127db96d56Sopenharmony_ci * including commercial applications, and to alter it and redistribute it 137db96d56Sopenharmony_ci * freely, subject to the following restrictions: 147db96d56Sopenharmony_ci * 157db96d56Sopenharmony_ci * 1. The origin of this software must not be misrepresented; you must not 167db96d56Sopenharmony_ci * claim that you wrote the original software. If you use this software 177db96d56Sopenharmony_ci * in a product, an acknowledgment in the product documentation would be 187db96d56Sopenharmony_ci * appreciated but is not required. 197db96d56Sopenharmony_ci * 2. Altered source versions must be plainly marked as such, and must not be 207db96d56Sopenharmony_ci * misrepresented as being the original software. 217db96d56Sopenharmony_ci * 3. This notice may not be removed or altered from any source distribution. 227db96d56Sopenharmony_ci */ 237db96d56Sopenharmony_ci 247db96d56Sopenharmony_ci#include "row.h" 257db96d56Sopenharmony_ci#include "cursor.h" 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci#define clinic_state() (pysqlite_get_state_by_type(type)) 287db96d56Sopenharmony_ci#include "clinic/row.c.h" 297db96d56Sopenharmony_ci#undef clinic_state 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci/*[clinic input] 327db96d56Sopenharmony_cimodule _sqlite3 337db96d56Sopenharmony_ciclass _sqlite3.Row "pysqlite_Row *" "clinic_state()->RowType" 347db96d56Sopenharmony_ci[clinic start generated code]*/ 357db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=966c53403d7f3a40]*/ 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_cistatic int 387db96d56Sopenharmony_cirow_clear(pysqlite_Row *self) 397db96d56Sopenharmony_ci{ 407db96d56Sopenharmony_ci Py_CLEAR(self->data); 417db96d56Sopenharmony_ci Py_CLEAR(self->description); 427db96d56Sopenharmony_ci return 0; 437db96d56Sopenharmony_ci} 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_cistatic int 467db96d56Sopenharmony_cirow_traverse(pysqlite_Row *self, visitproc visit, void *arg) 477db96d56Sopenharmony_ci{ 487db96d56Sopenharmony_ci Py_VISIT(Py_TYPE(self)); 497db96d56Sopenharmony_ci Py_VISIT(self->data); 507db96d56Sopenharmony_ci Py_VISIT(self->description); 517db96d56Sopenharmony_ci return 0; 527db96d56Sopenharmony_ci} 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_cistatic void 557db96d56Sopenharmony_cipysqlite_row_dealloc(PyObject *self) 567db96d56Sopenharmony_ci{ 577db96d56Sopenharmony_ci PyTypeObject *tp = Py_TYPE(self); 587db96d56Sopenharmony_ci PyObject_GC_UnTrack(self); 597db96d56Sopenharmony_ci tp->tp_clear(self); 607db96d56Sopenharmony_ci tp->tp_free(self); 617db96d56Sopenharmony_ci Py_DECREF(tp); 627db96d56Sopenharmony_ci} 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci/*[clinic input] 657db96d56Sopenharmony_ci@classmethod 667db96d56Sopenharmony_ci_sqlite3.Row.__new__ as pysqlite_row_new 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_ci cursor: object(type='pysqlite_Cursor *', subclass_of='clinic_state()->CursorType') 697db96d56Sopenharmony_ci data: object(subclass_of='&PyTuple_Type') 707db96d56Sopenharmony_ci / 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci[clinic start generated code]*/ 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_cistatic PyObject * 757db96d56Sopenharmony_cipysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor, 767db96d56Sopenharmony_ci PyObject *data) 777db96d56Sopenharmony_ci/*[clinic end generated code: output=10d58b09a819a4c1 input=b9e954ca31345dbf]*/ 787db96d56Sopenharmony_ci{ 797db96d56Sopenharmony_ci pysqlite_Row *self; 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci assert(type != NULL && type->tp_alloc != NULL); 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_ci self = (pysqlite_Row *) type->tp_alloc(type, 0); 847db96d56Sopenharmony_ci if (self == NULL) 857db96d56Sopenharmony_ci return NULL; 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci self->data = Py_NewRef(data); 887db96d56Sopenharmony_ci self->description = Py_NewRef(cursor->description); 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci return (PyObject *) self; 917db96d56Sopenharmony_ci} 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ciPyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx) 947db96d56Sopenharmony_ci{ 957db96d56Sopenharmony_ci PyObject *item = PyTuple_GetItem(self->data, idx); 967db96d56Sopenharmony_ci return Py_XNewRef(item); 977db96d56Sopenharmony_ci} 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_cistatic int 1007db96d56Sopenharmony_ciequal_ignore_case(PyObject *left, PyObject *right) 1017db96d56Sopenharmony_ci{ 1027db96d56Sopenharmony_ci int eq = PyObject_RichCompareBool(left, right, Py_EQ); 1037db96d56Sopenharmony_ci if (eq) { /* equal or error */ 1047db96d56Sopenharmony_ci return eq; 1057db96d56Sopenharmony_ci } 1067db96d56Sopenharmony_ci if (!PyUnicode_Check(left) || !PyUnicode_Check(right)) { 1077db96d56Sopenharmony_ci return 0; 1087db96d56Sopenharmony_ci } 1097db96d56Sopenharmony_ci if (!PyUnicode_IS_ASCII(left) || !PyUnicode_IS_ASCII(right)) { 1107db96d56Sopenharmony_ci return 0; 1117db96d56Sopenharmony_ci } 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci Py_ssize_t len = PyUnicode_GET_LENGTH(left); 1147db96d56Sopenharmony_ci if (PyUnicode_GET_LENGTH(right) != len) { 1157db96d56Sopenharmony_ci return 0; 1167db96d56Sopenharmony_ci } 1177db96d56Sopenharmony_ci const Py_UCS1 *p1 = PyUnicode_1BYTE_DATA(left); 1187db96d56Sopenharmony_ci const Py_UCS1 *p2 = PyUnicode_1BYTE_DATA(right); 1197db96d56Sopenharmony_ci for (; len; len--, p1++, p2++) { 1207db96d56Sopenharmony_ci if (Py_TOLOWER(*p1) != Py_TOLOWER(*p2)) { 1217db96d56Sopenharmony_ci return 0; 1227db96d56Sopenharmony_ci } 1237db96d56Sopenharmony_ci } 1247db96d56Sopenharmony_ci return 1; 1257db96d56Sopenharmony_ci} 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_cistatic PyObject * 1287db96d56Sopenharmony_cipysqlite_row_subscript(pysqlite_Row *self, PyObject *idx) 1297db96d56Sopenharmony_ci{ 1307db96d56Sopenharmony_ci Py_ssize_t _idx; 1317db96d56Sopenharmony_ci Py_ssize_t nitems, i; 1327db96d56Sopenharmony_ci 1337db96d56Sopenharmony_ci if (PyLong_Check(idx)) { 1347db96d56Sopenharmony_ci _idx = PyNumber_AsSsize_t(idx, PyExc_IndexError); 1357db96d56Sopenharmony_ci if (_idx == -1 && PyErr_Occurred()) 1367db96d56Sopenharmony_ci return NULL; 1377db96d56Sopenharmony_ci if (_idx < 0) 1387db96d56Sopenharmony_ci _idx += PyTuple_GET_SIZE(self->data); 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ci PyObject *item = PyTuple_GetItem(self->data, _idx); 1417db96d56Sopenharmony_ci return Py_XNewRef(item); 1427db96d56Sopenharmony_ci } else if (PyUnicode_Check(idx)) { 1437db96d56Sopenharmony_ci nitems = PyTuple_Size(self->description); 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_ci for (i = 0; i < nitems; i++) { 1467db96d56Sopenharmony_ci PyObject *obj; 1477db96d56Sopenharmony_ci obj = PyTuple_GET_ITEM(self->description, i); 1487db96d56Sopenharmony_ci obj = PyTuple_GET_ITEM(obj, 0); 1497db96d56Sopenharmony_ci int eq = equal_ignore_case(idx, obj); 1507db96d56Sopenharmony_ci if (eq < 0) { 1517db96d56Sopenharmony_ci return NULL; 1527db96d56Sopenharmony_ci } 1537db96d56Sopenharmony_ci if (eq) { 1547db96d56Sopenharmony_ci /* found item */ 1557db96d56Sopenharmony_ci PyObject *item = PyTuple_GetItem(self->data, i); 1567db96d56Sopenharmony_ci return Py_XNewRef(item); 1577db96d56Sopenharmony_ci } 1587db96d56Sopenharmony_ci } 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "No item with that key"); 1617db96d56Sopenharmony_ci return NULL; 1627db96d56Sopenharmony_ci } 1637db96d56Sopenharmony_ci else if (PySlice_Check(idx)) { 1647db96d56Sopenharmony_ci return PyObject_GetItem(self->data, idx); 1657db96d56Sopenharmony_ci } 1667db96d56Sopenharmony_ci else { 1677db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "Index must be int or string"); 1687db96d56Sopenharmony_ci return NULL; 1697db96d56Sopenharmony_ci } 1707db96d56Sopenharmony_ci} 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_cistatic Py_ssize_t 1737db96d56Sopenharmony_cipysqlite_row_length(pysqlite_Row* self) 1747db96d56Sopenharmony_ci{ 1757db96d56Sopenharmony_ci return PyTuple_GET_SIZE(self->data); 1767db96d56Sopenharmony_ci} 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci/*[clinic input] 1797db96d56Sopenharmony_ci_sqlite3.Row.keys as pysqlite_row_keys 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ciReturns the keys of the row. 1827db96d56Sopenharmony_ci[clinic start generated code]*/ 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_cistatic PyObject * 1857db96d56Sopenharmony_cipysqlite_row_keys_impl(pysqlite_Row *self) 1867db96d56Sopenharmony_ci/*[clinic end generated code: output=efe3dfb3af6edc07 input=7549a122827c5563]*/ 1877db96d56Sopenharmony_ci{ 1887db96d56Sopenharmony_ci PyObject* list; 1897db96d56Sopenharmony_ci Py_ssize_t nitems, i; 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci list = PyList_New(0); 1927db96d56Sopenharmony_ci if (!list) { 1937db96d56Sopenharmony_ci return NULL; 1947db96d56Sopenharmony_ci } 1957db96d56Sopenharmony_ci nitems = PyTuple_Size(self->description); 1967db96d56Sopenharmony_ci 1977db96d56Sopenharmony_ci for (i = 0; i < nitems; i++) { 1987db96d56Sopenharmony_ci if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) { 1997db96d56Sopenharmony_ci Py_DECREF(list); 2007db96d56Sopenharmony_ci return NULL; 2017db96d56Sopenharmony_ci } 2027db96d56Sopenharmony_ci } 2037db96d56Sopenharmony_ci 2047db96d56Sopenharmony_ci return list; 2057db96d56Sopenharmony_ci} 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_cistatic PyObject* pysqlite_iter(pysqlite_Row* self) 2087db96d56Sopenharmony_ci{ 2097db96d56Sopenharmony_ci return PyObject_GetIter(self->data); 2107db96d56Sopenharmony_ci} 2117db96d56Sopenharmony_ci 2127db96d56Sopenharmony_cistatic Py_hash_t pysqlite_row_hash(pysqlite_Row *self) 2137db96d56Sopenharmony_ci{ 2147db96d56Sopenharmony_ci return PyObject_Hash(self->description) ^ PyObject_Hash(self->data); 2157db96d56Sopenharmony_ci} 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_cistatic PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid) 2187db96d56Sopenharmony_ci{ 2197db96d56Sopenharmony_ci if (opid != Py_EQ && opid != Py_NE) 2207db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 2217db96d56Sopenharmony_ci 2227db96d56Sopenharmony_ci pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self)); 2237db96d56Sopenharmony_ci if (PyObject_TypeCheck(_other, state->RowType)) { 2247db96d56Sopenharmony_ci pysqlite_Row *other = (pysqlite_Row *)_other; 2257db96d56Sopenharmony_ci int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ); 2267db96d56Sopenharmony_ci if (eq < 0) { 2277db96d56Sopenharmony_ci return NULL; 2287db96d56Sopenharmony_ci } 2297db96d56Sopenharmony_ci if (eq) { 2307db96d56Sopenharmony_ci return PyObject_RichCompare(self->data, other->data, opid); 2317db96d56Sopenharmony_ci } 2327db96d56Sopenharmony_ci return PyBool_FromLong(opid != Py_EQ); 2337db96d56Sopenharmony_ci } 2347db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 2357db96d56Sopenharmony_ci} 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_cistatic PyMethodDef row_methods[] = { 2387db96d56Sopenharmony_ci PYSQLITE_ROW_KEYS_METHODDEF 2397db96d56Sopenharmony_ci {NULL, NULL} 2407db96d56Sopenharmony_ci}; 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_cistatic PyType_Slot row_slots[] = { 2437db96d56Sopenharmony_ci {Py_tp_dealloc, pysqlite_row_dealloc}, 2447db96d56Sopenharmony_ci {Py_tp_hash, pysqlite_row_hash}, 2457db96d56Sopenharmony_ci {Py_tp_methods, row_methods}, 2467db96d56Sopenharmony_ci {Py_tp_richcompare, pysqlite_row_richcompare}, 2477db96d56Sopenharmony_ci {Py_tp_iter, pysqlite_iter}, 2487db96d56Sopenharmony_ci {Py_mp_length, pysqlite_row_length}, 2497db96d56Sopenharmony_ci {Py_mp_subscript, pysqlite_row_subscript}, 2507db96d56Sopenharmony_ci {Py_sq_length, pysqlite_row_length}, 2517db96d56Sopenharmony_ci {Py_sq_item, pysqlite_row_item}, 2527db96d56Sopenharmony_ci {Py_tp_new, pysqlite_row_new}, 2537db96d56Sopenharmony_ci {Py_tp_traverse, row_traverse}, 2547db96d56Sopenharmony_ci {Py_tp_clear, row_clear}, 2557db96d56Sopenharmony_ci {0, NULL}, 2567db96d56Sopenharmony_ci}; 2577db96d56Sopenharmony_ci 2587db96d56Sopenharmony_cistatic PyType_Spec row_spec = { 2597db96d56Sopenharmony_ci .name = MODULE_NAME ".Row", 2607db96d56Sopenharmony_ci .basicsize = sizeof(pysqlite_Row), 2617db96d56Sopenharmony_ci .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 2627db96d56Sopenharmony_ci Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), 2637db96d56Sopenharmony_ci .slots = row_slots, 2647db96d56Sopenharmony_ci}; 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_ciint 2677db96d56Sopenharmony_cipysqlite_row_setup_types(PyObject *module) 2687db96d56Sopenharmony_ci{ 2697db96d56Sopenharmony_ci PyObject *type = PyType_FromModuleAndSpec(module, &row_spec, NULL); 2707db96d56Sopenharmony_ci if (type == NULL) { 2717db96d56Sopenharmony_ci return -1; 2727db96d56Sopenharmony_ci } 2737db96d56Sopenharmony_ci pysqlite_state *state = pysqlite_get_state(module); 2747db96d56Sopenharmony_ci state->RowType = (PyTypeObject *)type; 2757db96d56Sopenharmony_ci return 0; 2767db96d56Sopenharmony_ci} 277