(root)/
Python-3.11.7/
Modules/
_sqlite/
row.c
       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  row_clear(pysqlite_Row *self)
      39  {
      40      Py_CLEAR(self->data);
      41      Py_CLEAR(self->description);
      42      return 0;
      43  }
      44  
      45  static int
      46  row_traverse(pysqlite_Row *self, visitproc visit, void *arg)
      47  {
      48      Py_VISIT(Py_TYPE(self));
      49      Py_VISIT(self->data);
      50      Py_VISIT(self->description);
      51      return 0;
      52  }
      53  
      54  static void
      55  pysqlite_row_dealloc(PyObject *self)
      56  {
      57      PyTypeObject *tp = Py_TYPE(self);
      58      PyObject_GC_UnTrack(self);
      59      tp->tp_clear(self);
      60      tp->tp_free(self);
      61      Py_DECREF(tp);
      62  }
      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  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      self = (pysqlite_Row *) type->tp_alloc(type, 0);
      84      if (self == NULL)
      85          return NULL;
      86  
      87      self->data = Py_NewRef(data);
      88      self->description = Py_NewRef(cursor->description);
      89  
      90      return (PyObject *) self;
      91  }
      92  
      93  PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx)
      94  {
      95     PyObject *item = PyTuple_GetItem(self->data, idx);
      96     return Py_XNewRef(item);
      97  }
      98  
      99  static int
     100  equal_ignore_case(PyObject *left, PyObject *right)
     101  {
     102      int eq = PyObject_RichCompareBool(left, right, Py_EQ);
     103      if (eq) { /* equal or error */
     104          return eq;
     105      }
     106      if (!PyUnicode_Check(left) || !PyUnicode_Check(right)) {
     107          return 0;
     108      }
     109      if (!PyUnicode_IS_ASCII(left) || !PyUnicode_IS_ASCII(right)) {
     110          return 0;
     111      }
     112  
     113      Py_ssize_t len = PyUnicode_GET_LENGTH(left);
     114      if (PyUnicode_GET_LENGTH(right) != len) {
     115          return 0;
     116      }
     117      const Py_UCS1 *p1 = PyUnicode_1BYTE_DATA(left);
     118      const Py_UCS1 *p2 = PyUnicode_1BYTE_DATA(right);
     119      for (; len; len--, p1++, p2++) {
     120          if (Py_TOLOWER(*p1) != Py_TOLOWER(*p2)) {
     121              return 0;
     122          }
     123      }
     124      return 1;
     125  }
     126  
     127  static PyObject *
     128  pysqlite_row_subscript(pysqlite_Row *self, PyObject *idx)
     129  {
     130      Py_ssize_t _idx;
     131      Py_ssize_t nitems, i;
     132  
     133      if (PyLong_Check(idx)) {
     134          _idx = PyNumber_AsSsize_t(idx, PyExc_IndexError);
     135          if (_idx == -1 && PyErr_Occurred())
     136              return NULL;
     137          if (_idx < 0)
     138             _idx += PyTuple_GET_SIZE(self->data);
     139  
     140          PyObject *item = PyTuple_GetItem(self->data, _idx);
     141          return Py_XNewRef(item);
     142      } else if (PyUnicode_Check(idx)) {
     143          nitems = PyTuple_Size(self->description);
     144  
     145          for (i = 0; i < nitems; i++) {
     146              PyObject *obj;
     147              obj = PyTuple_GET_ITEM(self->description, i);
     148              obj = PyTuple_GET_ITEM(obj, 0);
     149              int eq = equal_ignore_case(idx, obj);
     150              if (eq < 0) {
     151                  return NULL;
     152              }
     153              if (eq) {
     154                  /* found item */
     155                  PyObject *item = PyTuple_GetItem(self->data, i);
     156                  return Py_XNewRef(item);
     157              }
     158          }
     159  
     160          PyErr_SetString(PyExc_IndexError, "No item with that key");
     161          return NULL;
     162      }
     163      else if (PySlice_Check(idx)) {
     164          return PyObject_GetItem(self->data, idx);
     165      }
     166      else {
     167          PyErr_SetString(PyExc_IndexError, "Index must be int or string");
     168          return NULL;
     169      }
     170  }
     171  
     172  static Py_ssize_t
     173  pysqlite_row_length(pysqlite_Row* self)
     174  {
     175      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  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      list = PyList_New(0);
     192      if (!list) {
     193          return NULL;
     194      }
     195      nitems = PyTuple_Size(self->description);
     196  
     197      for (i = 0; i < nitems; i++) {
     198          if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) {
     199              Py_DECREF(list);
     200              return NULL;
     201          }
     202      }
     203  
     204      return list;
     205  }
     206  
     207  static PyObject* pysqlite_iter(pysqlite_Row* self)
     208  {
     209      return PyObject_GetIter(self->data);
     210  }
     211  
     212  static Py_hash_t pysqlite_row_hash(pysqlite_Row *self)
     213  {
     214      return PyObject_Hash(self->description) ^ PyObject_Hash(self->data);
     215  }
     216  
     217  static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
     218  {
     219      if (opid != Py_EQ && opid != Py_NE)
     220          Py_RETURN_NOTIMPLEMENTED;
     221  
     222      pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self));
     223      if (PyObject_TypeCheck(_other, state->RowType)) {
     224          pysqlite_Row *other = (pysqlite_Row *)_other;
     225          int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
     226          if (eq < 0) {
     227              return NULL;
     228          }
     229          if (eq) {
     230              return PyObject_RichCompare(self->data, other->data, opid);
     231          }
     232          return PyBool_FromLong(opid != Py_EQ);
     233      }
     234      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  pysqlite_row_setup_types(PyObject *module)
     268  {
     269      PyObject *type = PyType_FromModuleAndSpec(module, &row_spec, NULL);
     270      if (type == NULL) {
     271          return -1;
     272      }
     273      pysqlite_state *state = pysqlite_get_state(module);
     274      state->RowType = (PyTypeObject *)type;
     275      return 0;
     276  }