LCOV - differential code coverage report
Current view: top level - src/pl/plpython - plpy_main.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 93.1 % 159 148 11 148
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 17 17 17
Baseline: 16@8cea358b128 Branches: 60.8 % 102 62 40 62
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 93.1 % 159 148 11 148
Function coverage date bins:
(240..) days: 100.0 % 17 17 17
Branch coverage date bins:
(240..) days: 60.8 % 102 62 40 62

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * PL/Python main entry points
                                  3                 :                :  *
                                  4                 :                :  * src/pl/plpython/plpy_main.c
                                  5                 :                :  */
                                  6                 :                : 
                                  7                 :                : #include "postgres.h"
                                  8                 :                : 
                                  9                 :                : #include "access/htup_details.h"
                                 10                 :                : #include "catalog/pg_proc.h"
                                 11                 :                : #include "catalog/pg_type.h"
                                 12                 :                : #include "commands/trigger.h"
                                 13                 :                : #include "executor/spi.h"
                                 14                 :                : #include "miscadmin.h"
                                 15                 :                : #include "plpy_elog.h"
                                 16                 :                : #include "plpy_exec.h"
                                 17                 :                : #include "plpy_main.h"
                                 18                 :                : #include "plpy_plpymodule.h"
                                 19                 :                : #include "plpy_procedure.h"
                                 20                 :                : #include "plpy_subxactobject.h"
                                 21                 :                : #include "plpython.h"
                                 22                 :                : #include "utils/guc.h"
                                 23                 :                : #include "utils/memutils.h"
                                 24                 :                : #include "utils/rel.h"
                                 25                 :                : #include "utils/syscache.h"
                                 26                 :                : 
                                 27                 :                : /*
                                 28                 :                :  * exported functions
                                 29                 :                :  */
                                 30                 :                : 
 4501 peter_e@gmx.net            31                 :CBC          23 : PG_MODULE_MAGIC;
                                 32                 :                : 
  769 andres@anarazel.de         33                 :             26 : PG_FUNCTION_INFO_V1(plpython3_validator);
                                 34                 :             26 : PG_FUNCTION_INFO_V1(plpython3_call_handler);
                                 35                 :              8 : PG_FUNCTION_INFO_V1(plpython3_inline_handler);
                                 36                 :                : 
                                 37                 :                : 
                                 38                 :                : static bool PLy_procedure_is_trigger(Form_pg_proc procStruct);
                                 39                 :                : static void plpython_error_callback(void *arg);
                                 40                 :                : static void plpython_inline_error_callback(void *arg);
                                 41                 :                : static void PLy_init_interp(void);
                                 42                 :                : 
                                 43                 :                : static PLyExecutionContext *PLy_push_execution_context(bool atomic_context);
                                 44                 :                : static void PLy_pop_execution_context(void);
                                 45                 :                : 
                                 46                 :                : /* static state for Python library conflict detection */
                                 47                 :                : static int *plpython_version_bitmask_ptr = NULL;
                                 48                 :                : static int  plpython_version_bitmask = 0;
                                 49                 :                : 
                                 50                 :                : /* initialize global variables */
                                 51                 :                : PyObject   *PLy_interp_globals = NULL;
                                 52                 :                : 
                                 53                 :                : /* this doesn't need to be global; use PLy_current_execution_context() */
                                 54                 :                : static PLyExecutionContext *PLy_execution_contexts = NULL;
                                 55                 :                : 
                                 56                 :                : 
                                 57                 :                : void
 4501 peter_e@gmx.net            58                 :             23 : _PG_init(void)
                                 59                 :                : {
                                 60                 :                :     int       **bitmask_ptr;
                                 61                 :                : 
                                 62                 :                :     /*
                                 63                 :                :      * Set up a shared bitmask variable telling which Python version(s) are
                                 64                 :                :      * loaded into this process's address space.  If there's more than one, we
                                 65                 :                :      * cannot call into libpython for fear of causing crashes.  But postpone
                                 66                 :                :      * the actual failure for later, so that operations like pg_restore can
                                 67                 :                :      * load more than one plpython library so long as they don't try to do
                                 68                 :                :      * anything much with the language.
                                 69                 :                :      *
                                 70                 :                :      * While we only support Python 3 these days, somebody might create an
                                 71                 :                :      * out-of-tree version adding back support for Python 2. Conflicts with
                                 72                 :                :      * such an extension should be detected.
                                 73                 :                :      */
 3016 tgl@sss.pgh.pa.us          74                 :             23 :     bitmask_ptr = (int **) find_rendezvous_variable("plpython_version_bitmask");
                                 75         [ +  - ]:             23 :     if (!(*bitmask_ptr))        /* am I the first? */
                                 76                 :             23 :         *bitmask_ptr = &plpython_version_bitmask;
                                 77                 :                :     /* Retain pointer to the agreed-on shared variable ... */
                                 78                 :             23 :     plpython_version_bitmask_ptr = *bitmask_ptr;
                                 79                 :                :     /* ... and announce my presence */
                                 80                 :             23 :     *plpython_version_bitmask_ptr |= (1 << PY_MAJOR_VERSION);
                                 81                 :                : 
                                 82                 :                :     /*
                                 83                 :                :      * This should be safe even in the presence of conflicting plpythons, and
                                 84                 :                :      * it's necessary to do it before possibly throwing a conflict error, or
                                 85                 :                :      * the error message won't get localized.
                                 86                 :                :      */
                                 87                 :             23 :     pg_bindtextdomain(TEXTDOMAIN);
                                 88                 :             23 : }
                                 89                 :                : 
                                 90                 :                : /*
                                 91                 :                :  * Perform one-time setup of PL/Python, after checking for a conflict
                                 92                 :                :  * with other versions of Python.
                                 93                 :                :  */
                                 94                 :                : static void
                                 95                 :            945 : PLy_initialize(void)
                                 96                 :                : {
                                 97                 :                :     static bool inited = false;
                                 98                 :                : 
                                 99                 :                :     /*
                                100                 :                :      * Check for multiple Python libraries before actively doing anything with
                                101                 :                :      * libpython.  This must be repeated on each entry to PL/Python, in case a
                                102                 :                :      * conflicting library got loaded since we last looked.
                                103                 :                :      *
                                104                 :                :      * It is attractive to weaken this error from FATAL to ERROR, but there
                                105                 :                :      * would be corner cases, so it seems best to be conservative.
                                106                 :                :      */
                                107         [ -  + ]:            945 :     if (*plpython_version_bitmask_ptr != (1 << PY_MAJOR_VERSION))
 3016 tgl@sss.pgh.pa.us         108         [ #  # ]:UBC           0 :         ereport(FATAL,
                                109                 :                :                 (errmsg("multiple Python libraries are present in session"),
                                110                 :                :                  errdetail("Only one Python major version can be used in one session.")));
                                111                 :                : 
                                112                 :                :     /* The rest should only be done once per session */
 3016 tgl@sss.pgh.pa.us         113         [ +  + ]:CBC         945 :     if (inited)
                                114                 :            922 :         return;
                                115                 :                : 
 4501 peter_e@gmx.net           116                 :             23 :     PyImport_AppendInittab("plpy", PyInit_plpy);
                                117                 :             23 :     Py_Initialize();
                                118                 :             23 :     PyImport_ImportModule("plpy");
                                119                 :             23 :     PLy_init_interp();
                                120                 :             23 :     PLy_init_plpy();
                                121         [ -  + ]:             23 :     if (PyErr_Occurred())
 4501 peter_e@gmx.net           122                 :UBC           0 :         PLy_elog(FATAL, "untrapped error in initialization");
                                123                 :                : 
 4501 peter_e@gmx.net           124                 :CBC          23 :     init_procedure_caches();
                                125                 :                : 
                                126                 :             23 :     explicit_subtransactions = NIL;
                                127                 :                : 
 4415 tgl@sss.pgh.pa.us         128                 :             23 :     PLy_execution_contexts = NULL;
                                129                 :                : 
 4501 peter_e@gmx.net           130                 :             23 :     inited = true;
                                131                 :                : }
                                132                 :                : 
                                133                 :                : /*
                                134                 :                :  * This should be called only once, from PLy_initialize. Initialize the Python
                                135                 :                :  * interpreter and global data.
                                136                 :                :  */
                                137                 :                : static void
                                138                 :             23 : PLy_init_interp(void)
                                139                 :                : {
                                140                 :                :     static PyObject *PLy_interp_safe_globals = NULL;
                                141                 :                :     PyObject   *mainmod;
                                142                 :                : 
                                143                 :             23 :     mainmod = PyImport_AddModule("__main__");
                                144   [ +  -  -  + ]:             23 :     if (mainmod == NULL || PyErr_Occurred())
 4501 peter_e@gmx.net           145                 :UBC           0 :         PLy_elog(ERROR, "could not import \"__main__\" module");
 4501 peter_e@gmx.net           146                 :CBC          23 :     Py_INCREF(mainmod);
                                147                 :             23 :     PLy_interp_globals = PyModule_GetDict(mainmod);
                                148                 :             23 :     PLy_interp_safe_globals = PyDict_New();
 4415 tgl@sss.pgh.pa.us         149         [ -  + ]:             23 :     if (PLy_interp_safe_globals == NULL)
 2357 peter_e@gmx.net           150                 :UBC           0 :         PLy_elog(ERROR, NULL);
 4501 peter_e@gmx.net           151                 :CBC          23 :     PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals);
                                152                 :             23 :     Py_DECREF(mainmod);
                                153   [ +  -  -  + ]:             23 :     if (PLy_interp_globals == NULL || PyErr_Occurred())
 4501 peter_e@gmx.net           154                 :UBC           0 :         PLy_elog(ERROR, "could not initialize globals");
 4501 peter_e@gmx.net           155                 :CBC          23 : }
                                156                 :                : 
                                157                 :                : Datum
  769 andres@anarazel.de        158                 :            247 : plpython3_validator(PG_FUNCTION_ARGS)
                                159                 :                : {
 4501 peter_e@gmx.net           160                 :            247 :     Oid         funcoid = PG_GETARG_OID(0);
                                161                 :                :     HeapTuple   tuple;
                                162                 :                :     Form_pg_proc procStruct;
                                163                 :                :     bool        is_trigger;
                                164                 :                : 
 3709 noah@leadboat.com         165         [ -  + ]:            247 :     if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
 3709 noah@leadboat.com         166                 :UBC           0 :         PG_RETURN_VOID();
                                167                 :                : 
 4501 peter_e@gmx.net           168         [ +  + ]:CBC         247 :     if (!check_function_bodies)
                                169                 :              1 :         PG_RETURN_VOID();
                                170                 :                : 
                                171                 :                :     /* Do this only after making sure we need to do something */
 3016 tgl@sss.pgh.pa.us         172                 :            246 :     PLy_initialize();
                                173                 :                : 
                                174                 :                :     /* Get the new function's pg_proc entry */
 4501 peter_e@gmx.net           175                 :            246 :     tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
                                176         [ -  + ]:            246 :     if (!HeapTupleIsValid(tuple))
 4501 peter_e@gmx.net           177         [ #  # ]:UBC           0 :         elog(ERROR, "cache lookup failed for function %u", funcoid);
 4501 peter_e@gmx.net           178                 :CBC         246 :     procStruct = (Form_pg_proc) GETSTRUCT(tuple);
                                179                 :                : 
                                180                 :            246 :     is_trigger = PLy_procedure_is_trigger(procStruct);
                                181                 :                : 
                                182                 :            246 :     ReleaseSysCache(tuple);
                                183                 :                : 
                                184                 :                :     /* We can't validate triggers against any particular table ... */
 4097 tgl@sss.pgh.pa.us         185                 :            246 :     PLy_procedure_get(funcoid, InvalidOid, is_trigger);
                                186                 :                : 
 4501 peter_e@gmx.net           187                 :            245 :     PG_RETURN_VOID();
                                188                 :                : }
                                189                 :                : 
                                190                 :                : Datum
  769 andres@anarazel.de        191                 :            678 : plpython3_call_handler(PG_FUNCTION_ARGS)
                                192                 :                : {
                                193                 :                :     bool        nonatomic;
                                194                 :                :     Datum       retval;
                                195                 :                :     PLyExecutionContext *exec_ctx;
                                196                 :                :     ErrorContextCallback plerrcontext;
                                197                 :                : 
 3016 tgl@sss.pgh.pa.us         198                 :            678 :     PLy_initialize();
                                199                 :                : 
 2274 peter_e@gmx.net           200                 :           1410 :     nonatomic = fcinfo->context &&
                                201   [ +  +  +  + ]:            686 :         IsA(fcinfo->context, CallContext) &&
                                202         [ +  + ]:              8 :         !castNode(CallContext, fcinfo->context)->atomic;
                                203                 :                : 
                                204                 :                :     /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
                                205         [ -  + ]:            678 :     if (SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0) != SPI_OK_CONNECT)
 4501 peter_e@gmx.net           206         [ #  # ]:UBC           0 :         elog(ERROR, "SPI_connect failed");
                                207                 :                : 
                                208                 :                :     /*
                                209                 :                :      * Push execution context onto stack.  It is important that this get
                                210                 :                :      * popped again, so avoid putting anything that could throw error between
                                211                 :                :      * here and the PG_TRY.
                                212                 :                :      */
 2274 peter_e@gmx.net           213                 :CBC         678 :     exec_ctx = PLy_push_execution_context(!nonatomic);
                                214                 :                : 
 4501                           215         [ +  + ]:            678 :     PG_TRY();
                                216                 :                :     {
 4097 tgl@sss.pgh.pa.us         217                 :            678 :         Oid         funcoid = fcinfo->flinfo->fn_oid;
                                218                 :                :         PLyProcedure *proc;
                                219                 :                : 
                                220                 :                :         /*
                                221                 :                :          * Setup error traceback support for ereport().  Note that the PG_TRY
                                222                 :                :          * structure pops this for us again at exit, so we needn't do that
                                223                 :                :          * explicitly, nor do we risk the callback getting called after we've
                                224                 :                :          * destroyed the exec_ctx.
                                225                 :                :          */
 2251                           226                 :            678 :         plerrcontext.callback = plpython_error_callback;
                                227                 :            678 :         plerrcontext.arg = exec_ctx;
                                228                 :            678 :         plerrcontext.previous = error_context_stack;
                                229                 :            678 :         error_context_stack = &plerrcontext;
                                230                 :                : 
 4501 peter_e@gmx.net           231   [ +  +  +  + ]:            678 :         if (CALLED_AS_TRIGGER(fcinfo))
                                232                 :             37 :         {
 4097 tgl@sss.pgh.pa.us         233                 :             46 :             Relation    tgrel = ((TriggerData *) fcinfo->context)->tg_relation;
                                234                 :                :             HeapTuple   trv;
                                235                 :                : 
                                236                 :             46 :             proc = PLy_procedure_get(funcoid, RelationGetRelid(tgrel), true);
 4415                           237                 :             46 :             exec_ctx->curr_proc = proc;
 4501 peter_e@gmx.net           238                 :             46 :             trv = PLy_exec_trigger(fcinfo, proc);
                                239                 :             37 :             retval = PointerGetDatum(trv);
                                240                 :                :         }
                                241                 :                :         else
                                242                 :                :         {
 4097 tgl@sss.pgh.pa.us         243                 :            632 :             proc = PLy_procedure_get(funcoid, InvalidOid, false);
 4415                           244                 :            629 :             exec_ctx->curr_proc = proc;
 4501 peter_e@gmx.net           245                 :            629 :             retval = PLy_exec_function(fcinfo, proc);
                                246                 :                :         }
                                247                 :                :     }
                                248                 :             93 :     PG_CATCH();
                                249                 :                :     {
 4415 tgl@sss.pgh.pa.us         250                 :             93 :         PLy_pop_execution_context();
 4501 peter_e@gmx.net           251                 :             93 :         PyErr_Clear();
                                252                 :             93 :         PG_RE_THROW();
                                253                 :                :     }
                                254         [ -  + ]:            585 :     PG_END_TRY();
                                255                 :                : 
                                256                 :                :     /* Destroy the execution context */
 4415 tgl@sss.pgh.pa.us         257                 :            585 :     PLy_pop_execution_context();
                                258                 :                : 
 4501 peter_e@gmx.net           259                 :            585 :     return retval;
                                260                 :                : }
                                261                 :                : 
                                262                 :                : Datum
  769 andres@anarazel.de        263                 :             21 : plpython3_inline_handler(PG_FUNCTION_ARGS)
                                264                 :                : {
 1905                           265                 :             21 :     LOCAL_FCINFO(fake_fcinfo, 0);
 4501 peter_e@gmx.net           266                 :             21 :     InlineCodeBlock *codeblock = (InlineCodeBlock *) DatumGetPointer(PG_GETARG_DATUM(0));
                                267                 :                :     FmgrInfo    flinfo;
                                268                 :                :     PLyProcedure proc;
                                269                 :                :     PLyExecutionContext *exec_ctx;
                                270                 :                :     ErrorContextCallback plerrcontext;
                                271                 :                : 
 3016 tgl@sss.pgh.pa.us         272                 :             21 :     PLy_initialize();
                                273                 :                : 
                                274                 :                :     /* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
 2274 peter_e@gmx.net           275         [ -  + ]:             21 :     if (SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC) != SPI_OK_CONNECT)
 4501 peter_e@gmx.net           276         [ #  # ]:UBC           0 :         elog(ERROR, "SPI_connect failed");
                                277                 :                : 
 1905 andres@anarazel.de        278   [ +  -  +  -  :CBC         105 :     MemSet(fcinfo, 0, SizeForFunctionCallInfo(0));
                                     +  -  +  -  +  
                                                 + ]
 4501 peter_e@gmx.net           279   [ +  -  +  -  :            147 :     MemSet(&flinfo, 0, sizeof(flinfo));
                                     +  -  +  -  +  
                                                 + ]
 1905 andres@anarazel.de        280                 :             21 :     fake_fcinfo->flinfo = &flinfo;
 4501 peter_e@gmx.net           281                 :             21 :     flinfo.fn_oid = InvalidOid;
                                282                 :             21 :     flinfo.fn_mcxt = CurrentMemoryContext;
                                283                 :                : 
                                284   [ +  -  +  -  :            861 :     MemSet(&proc, 0, sizeof(PLyProcedure));
                                     +  -  +  -  +  
                                                 + ]
 3083 tgl@sss.pgh.pa.us         285                 :             21 :     proc.mcxt = AllocSetContextCreate(TopMemoryContext,
                                286                 :                :                                       "__plpython_inline_block",
                                287                 :                :                                       ALLOCSET_DEFAULT_SIZES);
                                288                 :             21 :     proc.pyname = MemoryContextStrdup(proc.mcxt, "__plpython_inline_block");
 3276 peter_e@gmx.net           289                 :             21 :     proc.langid = codeblock->langOid;
                                290                 :                : 
                                291                 :                :     /*
                                292                 :                :      * This is currently sufficient to get PLy_exec_function to work, but
                                293                 :                :      * someday we might need to be honest and use PLy_output_setup_func.
                                294                 :                :      */
 2341 tgl@sss.pgh.pa.us         295                 :             21 :     proc.result.typoid = VOIDOID;
                                296                 :                : 
                                297                 :                :     /*
                                298                 :                :      * Push execution context onto stack.  It is important that this get
                                299                 :                :      * popped again, so avoid putting anything that could throw error between
                                300                 :                :      * here and the PG_TRY.
                                301                 :                :      */
 2274 peter_e@gmx.net           302                 :             21 :     exec_ctx = PLy_push_execution_context(codeblock->atomic);
                                303                 :                : 
 4501                           304         [ +  + ]:             21 :     PG_TRY();
                                305                 :                :     {
                                306                 :                :         /*
                                307                 :                :          * Setup error traceback support for ereport().
                                308                 :                :          * plpython_inline_error_callback doesn't currently need exec_ctx, but
                                309                 :                :          * for consistency with plpython3_call_handler we do it the same way.
                                310                 :                :          */
 2251 tgl@sss.pgh.pa.us         311                 :             21 :         plerrcontext.callback = plpython_inline_error_callback;
                                312                 :             21 :         plerrcontext.arg = exec_ctx;
                                313                 :             21 :         plerrcontext.previous = error_context_stack;
                                314                 :             21 :         error_context_stack = &plerrcontext;
                                315                 :                : 
 4501 peter_e@gmx.net           316                 :             21 :         PLy_procedure_compile(&proc, codeblock->source_text);
 4415 tgl@sss.pgh.pa.us         317                 :             21 :         exec_ctx->curr_proc = &proc;
 1905 andres@anarazel.de        318                 :             21 :         PLy_exec_function(fake_fcinfo, &proc);
                                319                 :                :     }
 4501 peter_e@gmx.net           320                 :             11 :     PG_CATCH();
                                321                 :                :     {
 4415 tgl@sss.pgh.pa.us         322                 :             11 :         PLy_pop_execution_context();
 4501 peter_e@gmx.net           323                 :             11 :         PLy_procedure_delete(&proc);
                                324                 :             11 :         PyErr_Clear();
                                325                 :             11 :         PG_RE_THROW();
                                326                 :                :     }
                                327         [ -  + ]:             10 :     PG_END_TRY();
                                328                 :                : 
                                329                 :                :     /* Destroy the execution context */
 4415 tgl@sss.pgh.pa.us         330                 :             10 :     PLy_pop_execution_context();
                                331                 :                : 
                                332                 :                :     /* Now clean up the transient procedure we made */
                                333                 :             10 :     PLy_procedure_delete(&proc);
                                334                 :                : 
 4501 peter_e@gmx.net           335                 :             10 :     PG_RETURN_VOID();
                                336                 :                : }
                                337                 :                : 
                                338                 :                : static bool
 4326 bruce@momjian.us          339                 :            246 : PLy_procedure_is_trigger(Form_pg_proc procStruct)
                                340                 :                : {
 1501 tgl@sss.pgh.pa.us         341                 :            246 :     return (procStruct->prorettype == TRIGGEROID);
                                342                 :                : }
                                343                 :                : 
                                344                 :                : static void
 4501 peter_e@gmx.net           345                 :            452 : plpython_error_callback(void *arg)
                                346                 :                : {
 2251 tgl@sss.pgh.pa.us         347                 :            452 :     PLyExecutionContext *exec_ctx = (PLyExecutionContext *) arg;
                                348                 :                : 
 4415                           349         [ +  + ]:            452 :     if (exec_ctx->curr_proc)
                                350                 :                :     {
 2327 peter_e@gmx.net           351         [ +  + ]:            449 :         if (exec_ctx->curr_proc->is_procedure)
                                352                 :              4 :             errcontext("PL/Python procedure \"%s\"",
                                353                 :                :                        PLy_procedure_name(exec_ctx->curr_proc));
                                354                 :                :         else
                                355                 :            445 :             errcontext("PL/Python function \"%s\"",
                                356                 :                :                        PLy_procedure_name(exec_ctx->curr_proc));
                                357                 :                :     }
 4501                           358                 :            452 : }
                                359                 :                : 
                                360                 :                : static void
                                361                 :             28 : plpython_inline_error_callback(void *arg)
                                362                 :                : {
                                363                 :             28 :     errcontext("PL/Python anonymous code block");
                                364                 :             28 : }
                                365                 :                : 
                                366                 :                : PLyExecutionContext *
 4415 tgl@sss.pgh.pa.us         367                 :           1410 : PLy_current_execution_context(void)
                                368                 :                : {
                                369         [ -  + ]:           1410 :     if (PLy_execution_contexts == NULL)
 4415 tgl@sss.pgh.pa.us         370         [ #  # ]:UBC           0 :         elog(ERROR, "no Python function is currently executing");
                                371                 :                : 
 4415 tgl@sss.pgh.pa.us         372                 :CBC        1410 :     return PLy_execution_contexts;
                                373                 :                : }
                                374                 :                : 
                                375                 :                : MemoryContext
 3083                           376                 :            779 : PLy_get_scratch_context(PLyExecutionContext *context)
                                377                 :                : {
                                378                 :                :     /*
                                379                 :                :      * A scratch context might never be needed in a given plpython procedure,
                                380                 :                :      * so allocate it on first request.
                                381                 :                :      */
                                382         [ +  + ]:            779 :     if (context->scratch_ctx == NULL)
                                383                 :            433 :         context->scratch_ctx =
                                384                 :            433 :             AllocSetContextCreate(TopTransactionContext,
                                385                 :                :                                   "PL/Python scratch context",
                                386                 :                :                                   ALLOCSET_DEFAULT_SIZES);
                                387                 :            779 :     return context->scratch_ctx;
                                388                 :                : }
                                389                 :                : 
                                390                 :                : static PLyExecutionContext *
 2274 peter_e@gmx.net           391                 :            699 : PLy_push_execution_context(bool atomic_context)
                                392                 :                : {
                                393                 :                :     PLyExecutionContext *context;
                                394                 :                : 
                                395                 :                :     /* Pick a memory context similar to what SPI uses. */
                                396                 :                :     context = (PLyExecutionContext *)
                                397         [ +  + ]:            699 :         MemoryContextAlloc(atomic_context ? TopTransactionContext : PortalContext,
                                398                 :                :                            sizeof(PLyExecutionContext));
 4415 tgl@sss.pgh.pa.us         399                 :            699 :     context->curr_proc = NULL;
 3083                           400                 :            699 :     context->scratch_ctx = NULL;
 4415                           401                 :            699 :     context->next = PLy_execution_contexts;
                                402                 :            699 :     PLy_execution_contexts = context;
                                403                 :            699 :     return context;
                                404                 :                : }
                                405                 :                : 
                                406                 :                : static void
                                407                 :            699 : PLy_pop_execution_context(void)
                                408                 :                : {
 4326 bruce@momjian.us          409                 :            699 :     PLyExecutionContext *context = PLy_execution_contexts;
                                410                 :                : 
 4415 tgl@sss.pgh.pa.us         411         [ -  + ]:            699 :     if (context == NULL)
 4415 tgl@sss.pgh.pa.us         412         [ #  # ]:UBC           0 :         elog(ERROR, "no Python function is currently executing");
                                413                 :                : 
 4415 tgl@sss.pgh.pa.us         414                 :CBC         699 :     PLy_execution_contexts = context->next;
                                415                 :                : 
 3083                           416         [ +  + ]:            699 :     if (context->scratch_ctx)
                                417                 :            416 :         MemoryContextDelete(context->scratch_ctx);
                                418                 :            699 :     pfree(context);
 4415                           419                 :            699 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622