LCOV - code coverage report
Current view: top level - src/pl/plpython - plpy_planobject.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 87.8 % 41 36
Test Date: 2026-07-18 08:15:45 Functions: 100.0 % 7 7
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 50.0 % 16 8

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * the PLyPlan class
       3                 :             :  *
       4                 :             :  * src/pl/plpython/plpy_planobject.c
       5                 :             :  */
       6                 :             : 
       7                 :             : #include "postgres.h"
       8                 :             : 
       9                 :             : #include "plpy_cursorobject.h"
      10                 :             : #include "plpy_planobject.h"
      11                 :             : #include "plpy_spi.h"
      12                 :             : #include "plpy_util.h"
      13                 :             : #include "utils/memutils.h"
      14                 :             : 
      15                 :             : static void PLy_plan_dealloc(PLyPlanObject *self);
      16                 :             : static PyObject *PLy_plan_cursor(PyObject *self, PyObject *args);
      17                 :             : static PyObject *PLy_plan_execute(PyObject *self, PyObject *args);
      18                 :             : static PyObject *PLy_plan_status(PyObject *self, PyObject *args);
      19                 :             : 
      20                 :             : static char PLy_plan_doc[] = "Store a PostgreSQL plan";
      21                 :             : 
      22                 :             : static PyMethodDef PLy_plan_methods[] = {
      23                 :             :     {"cursor", PLy_plan_cursor, METH_VARARGS, NULL},
      24                 :             :     {"execute", PLy_plan_execute, METH_VARARGS, NULL},
      25                 :             :     {"status", PLy_plan_status, METH_VARARGS, NULL},
      26                 :             :     {NULL, NULL, 0, NULL}
      27                 :             : };
      28                 :             : 
      29                 :             : static PyType_Slot PLyPlan_slots[] =
      30                 :             : {
      31                 :             :     {
      32                 :             :         Py_tp_dealloc, PLy_plan_dealloc
      33                 :             :     },
      34                 :             :     {
      35                 :             :         Py_tp_doc, (char *) PLy_plan_doc
      36                 :             :     },
      37                 :             :     {
      38                 :             :         Py_tp_methods, PLy_plan_methods
      39                 :             :     },
      40                 :             :     {
      41                 :             :         0, NULL
      42                 :             :     }
      43                 :             : };
      44                 :             : 
      45                 :             : static PyType_Spec PLyPlan_spec =
      46                 :             : {
      47                 :             :     .name = "PLyPlan",
      48                 :             :     .basicsize = sizeof(PLyPlanObject),
      49                 :             :     .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
      50                 :             :     .slots = PLyPlan_slots,
      51                 :             : };
      52                 :             : 
      53                 :             : static PyTypeObject *PLy_PlanType;
      54                 :             : 
      55                 :             : void
      56                 :          23 : PLy_plan_init_type(void)
      57                 :             : {
      58                 :          23 :     PLy_PlanType = (PyTypeObject *) PyType_FromSpec(&PLyPlan_spec);
      59         [ -  + ]:          23 :     if (!PLy_PlanType)
      60         [ #  # ]:           0 :         elog(ERROR, "could not initialize PLy_PlanType");
      61                 :          23 : }
      62                 :             : 
      63                 :             : PyObject *
      64                 :          29 : PLy_plan_new(void)
      65                 :             : {
      66                 :             :     PLyPlanObject *ob;
      67                 :             : 
      68         [ -  + ]:          29 :     if ((ob = PyObject_New(PLyPlanObject, PLy_PlanType)) == NULL)
      69                 :           0 :         return NULL;
      70                 :             : #if PY_VERSION_HEX < 0x03080000
      71                 :             :     /* Workaround for Python issue 35810; no longer necessary in Python 3.8 */
      72                 :             :     Py_INCREF(PLy_PlanType);
      73                 :             : #endif
      74                 :             : 
      75                 :          29 :     ob->plan = NULL;
      76                 :          29 :     ob->nargs = 0;
      77                 :          29 :     ob->types = NULL;
      78                 :          29 :     ob->args = NULL;
      79                 :          29 :     ob->mcxt = NULL;
      80                 :             : 
      81                 :          29 :     return (PyObject *) ob;
      82                 :             : }
      83                 :             : 
      84                 :             : bool
      85                 :          22 : is_PLyPlanObject(PyObject *ob)
      86                 :             : {
      87                 :          22 :     return ob->ob_type == PLy_PlanType;
      88                 :             : }
      89                 :             : 
      90                 :             : static void
      91                 :          25 : PLy_plan_dealloc(PLyPlanObject *self)
      92                 :             : {
      93                 :             : #if PY_VERSION_HEX >= 0x03080000
      94                 :          25 :     PyTypeObject *tp = Py_TYPE(self);
      95                 :             : #endif
      96                 :             : 
      97         [ +  + ]:          25 :     if (self->plan)
      98                 :             :     {
      99                 :          21 :         SPI_freeplan(self->plan);
     100                 :          21 :         self->plan = NULL;
     101                 :             :     }
     102         [ +  - ]:          25 :     if (self->mcxt)
     103                 :             :     {
     104                 :          25 :         MemoryContextDelete(self->mcxt);
     105                 :          25 :         self->mcxt = NULL;
     106                 :             :     }
     107                 :             : 
     108                 :          25 :     PyObject_Free(self);
     109                 :             : #if PY_VERSION_HEX >= 0x03080000
     110                 :             :     /* This was not needed before Python 3.8 (Python issue 35810) */
     111                 :             :     Py_DECREF(tp);
     112                 :             : #endif
     113                 :          25 : }
     114                 :             : 
     115                 :             : 
     116                 :             : static PyObject *
     117                 :           1 : PLy_plan_cursor(PyObject *self, PyObject *args)
     118                 :             : {
     119                 :           1 :     PyObject   *planargs = NULL;
     120                 :             : 
     121         [ -  + ]:           1 :     if (!PyArg_ParseTuple(args, "|O", &planargs))
     122                 :           0 :         return NULL;
     123                 :             : 
     124                 :           1 :     return PLy_cursor_plan(self, planargs);
     125                 :             : }
     126                 :             : 
     127                 :             : 
     128                 :             : static PyObject *
     129                 :           1 : PLy_plan_execute(PyObject *self, PyObject *args)
     130                 :             : {
     131                 :           1 :     PyObject   *list = NULL;
     132                 :           1 :     long        limit = 0;
     133                 :             : 
     134         [ -  + ]:           1 :     if (!PyArg_ParseTuple(args, "|Ol", &list, &limit))
     135                 :           0 :         return NULL;
     136                 :             : 
     137                 :           1 :     return PLy_spi_execute_plan(self, list, limit);
     138                 :             : }
     139                 :             : 
     140                 :             : 
     141                 :             : static PyObject *
     142                 :           2 : PLy_plan_status(PyObject *self, PyObject *args)
     143                 :             : {
     144         [ +  - ]:           2 :     if (PyArg_ParseTuple(args, ":status"))
     145                 :             :     {
     146                 :             :         Py_INCREF(Py_True);
     147                 :           2 :         return Py_True;
     148                 :             :         /* return PyLong_FromLong(self->status); */
     149                 :             :     }
     150                 :           0 :     return NULL;
     151                 :             : }
        

Generated by: LCOV version 2.0-1