LCOV - code coverage report
Current view: top level - src/pl/plpython - plpy_resultobject.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 88.4 % 86 76
Test Date: 2026-02-28 14:14:49 Functions: 100.0 % 13 13
Legend: Lines:     hit not hit

            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          152 : PLy_result_new(void)
      90              : {
      91              :     PLyResultObject *ob;
      92              : 
      93          152 :     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          152 :     ob->status = Py_None;
     104          152 :     ob->nrows = PyLong_FromLong(-1);
     105          152 :     ob->rows = PyList_New(0);
     106          152 :     ob->tupdesc = NULL;
     107          152 :     if (!ob->rows)
     108              :     {
     109              :         Py_DECREF(ob);
     110            0 :         return NULL;
     111              :     }
     112              : 
     113          152 :     return (PyObject *) ob;
     114              : }
     115              : 
     116              : static void
     117          151 : PLy_result_dealloc(PLyResultObject *self)
     118              : {
     119              : #if PY_VERSION_HEX >= 0x03080000
     120          151 :     PyTypeObject *tp = Py_TYPE(self);
     121              : #endif
     122              : 
     123          151 :     Py_XDECREF(self->nrows);
     124          151 :     Py_XDECREF(self->rows);
     125          151 :     Py_XDECREF(self->status);
     126          151 :     if (self->tupdesc)
     127              :     {
     128           60 :         FreeTupleDesc(self->tupdesc);
     129           60 :         self->tupdesc = NULL;
     130              :     }
     131              : 
     132          151 :     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          151 : }
     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           28 : PLy_result_item(PyObject *arg, Py_ssize_t idx)
     245              : {
     246              :     PyObject   *rv;
     247           28 :     PLyResultObject *ob = (PLyResultObject *) arg;
     248              : 
     249           28 :     rv = PyList_GetItem(ob->rows, idx);
     250           28 :     if (rv != NULL)
     251              :         Py_INCREF(rv);
     252           28 :     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