LCOV - code coverage report
Current view: top level - src/pl/plpython - plpy_resultobject.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 79 90 87.8 %
Date: 2025-04-01 15:15:16 Functions: 13 13 100.0 %
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 "plpython.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          46 : PLy_result_init_type(void)
      82             : {
      83          46 :     PLy_ResultType = (PyTypeObject *) PyType_FromSpec(&PLyResult_spec);
      84          46 :     if (!PLy_ResultType)
      85           0 :         elog(ERROR, "could not initialize PLy_ResultType");
      86          46 : }
      87             : 
      88             : PyObject *
      89         304 : PLy_result_new(void)
      90             : {
      91             :     PLyResultObject *ob;
      92             : 
      93         304 :     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         304 :     Py_INCREF(Py_None);
     103         304 :     ob->status = Py_None;
     104         304 :     ob->nrows = PyLong_FromLong(-1);
     105         304 :     ob->rows = PyList_New(0);
     106         304 :     ob->tupdesc = NULL;
     107         304 :     if (!ob->rows)
     108             :     {
     109           0 :         Py_DECREF(ob);
     110           0 :         return NULL;
     111             :     }
     112             : 
     113         304 :     return (PyObject *) ob;
     114             : }
     115             : 
     116             : static void
     117         302 : PLy_result_dealloc(PLyResultObject *self)
     118             : {
     119             : #if PY_VERSION_HEX >= 0x03080000
     120         302 :     PyTypeObject *tp = Py_TYPE(self);
     121             : #endif
     122             : 
     123         302 :     Py_XDECREF(self->nrows);
     124         302 :     Py_XDECREF(self->rows);
     125         302 :     Py_XDECREF(self->status);
     126         302 :     if (self->tupdesc)
     127             :     {
     128         120 :         FreeTupleDesc(self->tupdesc);
     129         120 :         self->tupdesc = NULL;
     130             :     }
     131             : 
     132         302 :     PyObject_Free(self);
     133             : #if PY_VERSION_HEX >= 0x03080000
     134             :     /* This was not needed before Python 3.8 (Python issue 35810) */
     135         302 :     Py_DECREF(tp);
     136             : #endif
     137         302 : }
     138             : 
     139             : static PyObject *
     140           4 : PLy_result_colnames(PyObject *self, PyObject *unused)
     141             : {
     142           4 :     PLyResultObject *ob = (PLyResultObject *) self;
     143             :     PyObject   *list;
     144             :     int         i;
     145             : 
     146           4 :     if (!ob->tupdesc)
     147             :     {
     148           2 :         PLy_exception_set(PLy_exc_error, "command did not produce a result set");
     149           2 :         return NULL;
     150             :     }
     151             : 
     152           2 :     list = PyList_New(ob->tupdesc->natts);
     153           2 :     if (!list)
     154           0 :         return NULL;
     155           6 :     for (i = 0; i < ob->tupdesc->natts; i++)
     156             :     {
     157           4 :         Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
     158             : 
     159           4 :         PyList_SetItem(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
     160             :     }
     161             : 
     162           2 :     return list;
     163             : }
     164             : 
     165             : static PyObject *
     166           2 : PLy_result_coltypes(PyObject *self, PyObject *unused)
     167             : {
     168           2 :     PLyResultObject *ob = (PLyResultObject *) self;
     169             :     PyObject   *list;
     170             :     int         i;
     171             : 
     172           2 :     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           2 :     list = PyList_New(ob->tupdesc->natts);
     179           2 :     if (!list)
     180           0 :         return NULL;
     181           6 :     for (i = 0; i < ob->tupdesc->natts; i++)
     182             :     {
     183           4 :         Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
     184             : 
     185           4 :         PyList_SetItem(list, i, PyLong_FromLong(attr->atttypid));
     186             :     }
     187             : 
     188           2 :     return list;
     189             : }
     190             : 
     191             : static PyObject *
     192           2 : PLy_result_coltypmods(PyObject *self, PyObject *unused)
     193             : {
     194           2 :     PLyResultObject *ob = (PLyResultObject *) self;
     195             :     PyObject   *list;
     196             :     int         i;
     197             : 
     198           2 :     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           2 :     list = PyList_New(ob->tupdesc->natts);
     205           2 :     if (!list)
     206           0 :         return NULL;
     207           6 :     for (i = 0; i < ob->tupdesc->natts; i++)
     208             :     {
     209           4 :         Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
     210             : 
     211           4 :         PyList_SetItem(list, i, PyLong_FromLong(attr->atttypmod));
     212             :     }
     213             : 
     214           2 :     return list;
     215             : }
     216             : 
     217             : static PyObject *
     218          14 : PLy_result_nrows(PyObject *self, PyObject *args)
     219             : {
     220          14 :     PLyResultObject *ob = (PLyResultObject *) self;
     221             : 
     222          14 :     Py_INCREF(ob->nrows);
     223          14 :     return ob->nrows;
     224             : }
     225             : 
     226             : static PyObject *
     227           4 : PLy_result_status(PyObject *self, PyObject *args)
     228             : {
     229           4 :     PLyResultObject *ob = (PLyResultObject *) self;
     230             : 
     231           4 :     Py_INCREF(ob->status);
     232           4 :     return ob->status;
     233             : }
     234             : 
     235             : static Py_ssize_t
     236          26 : PLy_result_length(PyObject *arg)
     237             : {
     238          26 :     PLyResultObject *ob = (PLyResultObject *) arg;
     239             : 
     240          26 :     return PyList_Size(ob->rows);
     241             : }
     242             : 
     243             : static PyObject *
     244          56 : PLy_result_item(PyObject *arg, Py_ssize_t idx)
     245             : {
     246             :     PyObject   *rv;
     247          56 :     PLyResultObject *ob = (PLyResultObject *) arg;
     248             : 
     249          56 :     rv = PyList_GetItem(ob->rows, idx);
     250          56 :     if (rv != NULL)
     251          40 :         Py_INCREF(rv);
     252          56 :     return rv;
     253             : }
     254             : 
     255             : static PyObject *
     256           4 : PLy_result_str(PyObject *arg)
     257             : {
     258           4 :     PLyResultObject *ob = (PLyResultObject *) arg;
     259             : 
     260           4 :     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          92 : PLy_result_subscript(PyObject *arg, PyObject *item)
     269             : {
     270          92 :     PLyResultObject *ob = (PLyResultObject *) arg;
     271             : 
     272          92 :     return PyObject_GetItem(ob->rows, item);
     273             : }
     274             : 
     275             : static int
     276           4 : PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value)
     277             : {
     278           4 :     PLyResultObject *ob = (PLyResultObject *) arg;
     279             : 
     280           4 :     return PyObject_SetItem(ob->rows, item, value);
     281             : }

Generated by: LCOV version 1.14