LCOV - code coverage report
Current view: | top level - Modules/_sqlite - row.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 6 | 105 | 5.7 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 1 | 13 | 7.7 %
|  |  | Branches: | 1 | 70 | 1.4 %

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

Generated by: LCOV version 1.14