LCOV - code coverage report
Current view: top level - src/pl/plpython - plpy_resultobject.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 88.4 % 86 76
Test Date: 2026-07-18 10:15:36 Functions: 100.0 % 13 13
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 64.7 % 34 22

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * the PLyResult class
       3                 :             :  *
       4                 :             :  * src/pl/plpython/plpy_resultobject.c
       5                 :             :  */
       6                 :             : 
       7                 :             : #include "postgres.h"
       8                 :             : 
       9                 :             : #include "plpy_elog.h"
      10                 :             : #include "plpy_resultobject.h"
      11                 :             : #include "plpy_util.h"
      12                 :             : 
      13                 :             : static void PLy_result_dealloc(PLyResultObject *self);
      14                 :             : static PyObject *PLy_result_colnames(PyObject *self, PyObject *unused);
      15                 :             : static PyObject *PLy_result_coltypes(PyObject *self, PyObject *unused);
      16                 :             : static PyObject *PLy_result_coltypmods(PyObject *self, PyObject *unused);
      17                 :             : static PyObject *PLy_result_nrows(PyObject *self, PyObject *args);
      18                 :             : static PyObject *PLy_result_status(PyObject *self, PyObject *args);
      19                 :             : static Py_ssize_t PLy_result_length(PyObject *arg);
      20                 :             : static PyObject *PLy_result_item(PyObject *arg, Py_ssize_t idx);
      21                 :             : static PyObject *PLy_result_str(PyObject *arg);
      22                 :             : static PyObject *PLy_result_subscript(PyObject *arg, PyObject *item);
      23                 :             : static int  PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value);
      24                 :             : 
      25                 :             : static char PLy_result_doc[] = "Results of a PostgreSQL query";
      26                 :             : 
      27                 :             : static PyMethodDef PLy_result_methods[] = {
      28                 :             :     {"colnames", PLy_result_colnames, METH_NOARGS, NULL},
      29                 :             :     {"coltypes", PLy_result_coltypes, METH_NOARGS, NULL},
      30                 :             :     {"coltypmods", PLy_result_coltypmods, METH_NOARGS, NULL},
      31                 :             :     {"nrows", PLy_result_nrows, METH_VARARGS, NULL},
      32                 :             :     {"status", PLy_result_status, METH_VARARGS, NULL},
      33                 :             :     {NULL, NULL, 0, NULL}
      34                 :             : };
      35                 :             : 
      36                 :             : static PyType_Slot PLyResult_slots[] =
      37                 :             : {
      38                 :             :     {
      39                 :             :         Py_tp_dealloc, PLy_result_dealloc
      40                 :             :     },
      41                 :             :     {
      42                 :             :         Py_sq_length, PLy_result_length
      43                 :             :     },
      44                 :             :     {
      45                 :             :         Py_sq_item, PLy_result_item
      46                 :             :     },
      47                 :             :     {
      48                 :             :         Py_mp_length, PLy_result_length
      49                 :             :     },
      50                 :             :     {
      51                 :             :         Py_mp_subscript, PLy_result_subscript
      52                 :             :     },
      53                 :             :     {
      54                 :             :         Py_mp_ass_subscript, PLy_result_ass_subscript
      55                 :             :     },
      56                 :             :     {
      57                 :             :         Py_tp_str, PLy_result_str
      58                 :             :     },
      59                 :             :     {
      60                 :             :         Py_tp_doc, (char *) PLy_result_doc
      61                 :             :     },
      62                 :             :     {
      63                 :             :         Py_tp_methods, PLy_result_methods
      64                 :             :     },
      65                 :             :     {
      66                 :             :         0, NULL
      67                 :             :     }
      68                 :             : };
      69                 :             : 
      70                 :             : static PyType_Spec PLyResult_spec =
      71                 :             : {
      72                 :             :     .name = "PLyResult",
      73                 :             :     .basicsize = sizeof(PLyResultObject),
      74                 :             :     .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
      75                 :             :     .slots = PLyResult_slots,
      76                 :             : };
      77                 :             : 
      78                 :             : static PyTypeObject *PLy_ResultType;
      79                 :             : 
      80                 :             : void
      81                 :          23 : PLy_result_init_type(void)
      82                 :             : {
      83                 :          23 :     PLy_ResultType = (PyTypeObject *) PyType_FromSpec(&PLyResult_spec);
      84         [ -  + ]:          23 :     if (!PLy_ResultType)
      85         [ #  # ]:           0 :         elog(ERROR, "could not initialize PLy_ResultType");
      86                 :          23 : }
      87                 :             : 
      88                 :             : PyObject *
      89                 :         155 : PLy_result_new(void)
      90                 :             : {
      91                 :             :     PLyResultObject *ob;
      92                 :             : 
      93         [ -  + ]:         155 :     if ((ob = PyObject_New(PLyResultObject, PLy_ResultType)) == NULL)
      94                 :           0 :         return NULL;
      95                 :             : #if PY_VERSION_HEX < 0x03080000
      96                 :             :     /* Workaround for Python issue 35810; no longer necessary in Python 3.8 */
      97                 :             :     Py_INCREF(PLy_ResultType);
      98                 :             : #endif
      99                 :             : 
     100                 :             :     /* ob->tuples = NULL; */
     101                 :             : 
     102                 :             :     Py_INCREF(Py_None);
     103                 :         155 :     ob->status = Py_None;
     104                 :         155 :     ob->nrows = PyLong_FromLong(-1);
     105                 :         155 :     ob->rows = PyList_New(0);
     106                 :         155 :     ob->tupdesc = NULL;
     107         [ -  + ]:         155 :     if (!ob->rows)
     108                 :             :     {
     109                 :             :         Py_DECREF(ob);
     110                 :           0 :         return NULL;
     111                 :             :     }
     112                 :             : 
     113                 :         155 :     return (PyObject *) ob;
     114                 :             : }
     115                 :             : 
     116                 :             : static void
     117                 :         154 : PLy_result_dealloc(PLyResultObject *self)
     118                 :             : {
     119                 :             : #if PY_VERSION_HEX >= 0x03080000
     120                 :         154 :     PyTypeObject *tp = Py_TYPE(self);
     121                 :             : #endif
     122                 :             : 
     123                 :         154 :     Py_XDECREF(self->nrows);
     124                 :         154 :     Py_XDECREF(self->rows);
     125                 :         154 :     Py_XDECREF(self->status);
     126         [ +  + ]:         154 :     if (self->tupdesc)
     127                 :             :     {
     128                 :          62 :         FreeTupleDesc(self->tupdesc);
     129                 :          62 :         self->tupdesc = NULL;
     130                 :             :     }
     131                 :             : 
     132                 :         154 :     PyObject_Free(self);
     133                 :             : #if PY_VERSION_HEX >= 0x03080000
     134                 :             :     /* This was not needed before Python 3.8 (Python issue 35810) */
     135                 :             :     Py_DECREF(tp);
     136                 :             : #endif
     137                 :         154 : }
     138                 :             : 
     139                 :             : static PyObject *
     140                 :           2 : PLy_result_colnames(PyObject *self, PyObject *unused)
     141                 :             : {
     142                 :           2 :     PLyResultObject *ob = (PLyResultObject *) self;
     143                 :             :     PyObject   *list;
     144                 :             :     int         i;
     145                 :             : 
     146         [ +  + ]:           2 :     if (!ob->tupdesc)
     147                 :             :     {
     148                 :           1 :         PLy_exception_set(PLy_exc_error, "command did not produce a result set");
     149                 :           1 :         return NULL;
     150                 :             :     }
     151                 :             : 
     152                 :           1 :     list = PyList_New(ob->tupdesc->natts);
     153         [ -  + ]:           1 :     if (!list)
     154                 :           0 :         return NULL;
     155         [ +  + ]:           3 :     for (i = 0; i < ob->tupdesc->natts; i++)
     156                 :             :     {
     157                 :           2 :         Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
     158                 :             : 
     159                 :           2 :         PyList_SetItem(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
     160                 :             :     }
     161                 :             : 
     162                 :           1 :     return list;
     163                 :             : }
     164                 :             : 
     165                 :             : static PyObject *
     166                 :           1 : PLy_result_coltypes(PyObject *self, PyObject *unused)
     167                 :             : {
     168                 :           1 :     PLyResultObject *ob = (PLyResultObject *) self;
     169                 :             :     PyObject   *list;
     170                 :             :     int         i;
     171                 :             : 
     172         [ -  + ]:           1 :     if (!ob->tupdesc)
     173                 :             :     {
     174                 :           0 :         PLy_exception_set(PLy_exc_error, "command did not produce a result set");
     175                 :           0 :         return NULL;
     176                 :             :     }
     177                 :             : 
     178                 :           1 :     list = PyList_New(ob->tupdesc->natts);
     179         [ -  + ]:           1 :     if (!list)
     180                 :           0 :         return NULL;
     181         [ +  + ]:           3 :     for (i = 0; i < ob->tupdesc->natts; i++)
     182                 :             :     {
     183                 :           2 :         Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
     184                 :             : 
     185                 :           2 :         PyList_SetItem(list, i, PyLong_FromLong(attr->atttypid));
     186                 :             :     }
     187                 :             : 
     188                 :           1 :     return list;
     189                 :             : }
     190                 :             : 
     191                 :             : static PyObject *
     192                 :           1 : PLy_result_coltypmods(PyObject *self, PyObject *unused)
     193                 :             : {
     194                 :           1 :     PLyResultObject *ob = (PLyResultObject *) self;
     195                 :             :     PyObject   *list;
     196                 :             :     int         i;
     197                 :             : 
     198         [ -  + ]:           1 :     if (!ob->tupdesc)
     199                 :             :     {
     200                 :           0 :         PLy_exception_set(PLy_exc_error, "command did not produce a result set");
     201                 :           0 :         return NULL;
     202                 :             :     }
     203                 :             : 
     204                 :           1 :     list = PyList_New(ob->tupdesc->natts);
     205         [ -  + ]:           1 :     if (!list)
     206                 :           0 :         return NULL;
     207         [ +  + ]:           3 :     for (i = 0; i < ob->tupdesc->natts; i++)
     208                 :             :     {
     209                 :           2 :         Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
     210                 :             : 
     211                 :           2 :         PyList_SetItem(list, i, PyLong_FromLong(attr->atttypmod));
     212                 :             :     }
     213                 :             : 
     214                 :           1 :     return list;
     215                 :             : }
     216                 :             : 
     217                 :             : static PyObject *
     218                 :           7 : PLy_result_nrows(PyObject *self, PyObject *args)
     219                 :             : {
     220                 :           7 :     PLyResultObject *ob = (PLyResultObject *) self;
     221                 :             : 
     222         [ +  - ]:           7 :     Py_INCREF(ob->nrows);
     223                 :           7 :     return ob->nrows;
     224                 :             : }
     225                 :             : 
     226                 :             : static PyObject *
     227                 :           2 : PLy_result_status(PyObject *self, PyObject *args)
     228                 :             : {
     229                 :           2 :     PLyResultObject *ob = (PLyResultObject *) self;
     230                 :             : 
     231         [ +  - ]:           2 :     Py_INCREF(ob->status);
     232                 :           2 :     return ob->status;
     233                 :             : }
     234                 :             : 
     235                 :             : static Py_ssize_t
     236                 :          13 : PLy_result_length(PyObject *arg)
     237                 :             : {
     238                 :          13 :     PLyResultObject *ob = (PLyResultObject *) arg;
     239                 :             : 
     240                 :          13 :     return PyList_Size(ob->rows);
     241                 :             : }
     242                 :             : 
     243                 :             : static PyObject *
     244                 :          35 : PLy_result_item(PyObject *arg, Py_ssize_t idx)
     245                 :             : {
     246                 :             :     PyObject   *rv;
     247                 :          35 :     PLyResultObject *ob = (PLyResultObject *) arg;
     248                 :             : 
     249                 :          35 :     rv = PyList_GetItem(ob->rows, idx);
     250         [ +  + ]:          35 :     if (rv != NULL)
     251                 :             :         Py_INCREF(rv);
     252                 :          35 :     return rv;
     253                 :             : }
     254                 :             : 
     255                 :             : static PyObject *
     256                 :           2 : PLy_result_str(PyObject *arg)
     257                 :             : {
     258                 :           2 :     PLyResultObject *ob = (PLyResultObject *) arg;
     259                 :             : 
     260                 :           2 :     return PyUnicode_FromFormat("<%s status=%S nrows=%S rows=%S>",
     261                 :             :                                 "PLyResult",
     262                 :             :                                 ob->status,
     263                 :             :                                 ob->nrows,
     264                 :             :                                 ob->rows);
     265                 :             : }
     266                 :             : 
     267                 :             : static PyObject *
     268                 :          46 : PLy_result_subscript(PyObject *arg, PyObject *item)
     269                 :             : {
     270                 :          46 :     PLyResultObject *ob = (PLyResultObject *) arg;
     271                 :             : 
     272                 :          46 :     return PyObject_GetItem(ob->rows, item);
     273                 :             : }
     274                 :             : 
     275                 :             : static int
     276                 :           2 : PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value)
     277                 :             : {
     278                 :           2 :     PLyResultObject *ob = (PLyResultObject *) arg;
     279                 :             : 
     280                 :           2 :     return PyObject_SetItem(ob->rows, item, value);
     281                 :             : }
        

Generated by: LCOV version 2.0-1