PostgreSQL Source Code git master
Loading...
Searching...
No Matches
plpy_procedure.h File Reference
#include "plpy_typeio.h"
Include dependency graph for plpy_procedure.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PLySavedArgs
 
struct  PLyProcedure
 
struct  PLyProcedureKey
 
struct  PLyProcedureEntry
 

Typedefs

typedef enum PLyTrigType PLyTrigType
 
typedef struct PLySavedArgs PLySavedArgs
 
typedef struct PLyProcedure PLyProcedure
 
typedef struct PLyProcedureKey PLyProcedureKey
 
typedef struct PLyProcedureEntry PLyProcedureEntry
 

Enumerations

enum  PLyTrigType { PLPY_TRIGGER , PLPY_EVENT_TRIGGER , PLPY_NOT_TRIGGER }
 

Functions

void init_procedure_caches (void)
 
charPLy_procedure_name (PLyProcedure *proc)
 
PLyProcedurePLy_procedure_get (Oid fn_oid, Oid fn_rel, PLyTrigType is_trigger)
 
void PLy_procedure_compile (PLyProcedure *proc, const char *src)
 
void PLy_procedure_delete (PLyProcedure *proc)
 

Typedef Documentation

◆ PLyProcedure

◆ PLyProcedureEntry

◆ PLyProcedureKey

◆ PLySavedArgs

◆ PLyTrigType

Enumeration Type Documentation

◆ PLyTrigType

Enumerator
PLPY_TRIGGER 
PLPY_EVENT_TRIGGER 
PLPY_NOT_TRIGGER 

Definition at line 17 of file plpy_procedure.h.

18{
PLyTrigType
@ PLPY_EVENT_TRIGGER
@ PLPY_TRIGGER
@ PLPY_NOT_TRIGGER

Function Documentation

◆ init_procedure_caches()

void init_procedure_caches ( void  )
extern

Definition at line 30 of file plpy_procedure.c.

31{
33
35 hash_ctl.entrysize = sizeof(PLyProcedureEntry);
36 PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
38}
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:358
#define HASH_ELEM
Definition hsearch.h:95
#define HASH_BLOBS
Definition hsearch.h:97
static HTAB * PLy_procedure_cache
static int fb(int x)
Size keysize
Definition hsearch.h:75

References fb(), HASH_BLOBS, hash_create(), HASH_ELEM, HASHCTL::keysize, and PLy_procedure_cache.

Referenced by _PG_init().

◆ PLy_procedure_compile()

void PLy_procedure_compile ( PLyProcedure proc,
const char src 
)
extern

Definition at line 365 of file plpy_procedure.c.

366{
367 PyObject *crv = NULL;
368 char *msrc;
370
372
373 /*
374 * SD is private preserved data between calls. GD is global data shared by
375 * all functions
376 */
377 proc->statics = PyDict_New();
378 if (!proc->statics)
380 PyDict_SetItemString(proc->globals, "SD", proc->statics);
381
382 /*
383 * insert the function code into the interpreter
384 */
386 /* Save the mangled source for later inclusion in tracebacks */
387 proc->src = MemoryContextStrdup(proc->mcxt, msrc);
389 if (code0)
391 pfree(msrc);
392
393 if (crv != NULL)
394 {
395 int clen;
396 char call[NAMEDATALEN + 256];
397
398 Py_DECREF(crv);
399
400 /*
401 * compile a call to the function
402 */
403 clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
404 if (clen < 0 || clen >= sizeof(call))
405 elog(ERROR, "string would overflow buffer");
406 proc->code = Py_CompileString(call, "<string>", Py_eval_input);
407 if (proc->code != NULL)
408 return;
409 }
410
411 if (proc->proname)
412 PLy_elog(ERROR, "could not compile PL/Python function \"%s\"",
413 proc->proname);
414 else
415 PLy_elog(ERROR, "could not compile anonymous PL/Python code block");
416}
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define PLy_elog
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition mcxt.c:1768
void pfree(void *pointer)
Definition mcxt.c:1616
#define NAMEDATALEN
PyObject * PLy_interp_globals
Definition plpy_main.c:50
static char * PLy_procedure_munge_source(const char *name, const char *src)
#define snprintf
Definition port.h:260
PyObject * code
MemoryContext mcxt
PyObject * globals
PyObject * statics

References PLyProcedure::code, elog, ERROR, fb(), PLyProcedure::globals, PLyProcedure::mcxt, MemoryContextStrdup(), NAMEDATALEN, pfree(), PLy_elog, PLy_interp_globals, PLy_procedure_munge_source(), PLyProcedure::proname, PLyProcedure::pyname, snprintf, PLyProcedure::src, and PLyProcedure::statics.

Referenced by plpython3_inline_handler(), and PLy_procedure_create().

◆ PLy_procedure_delete()

void PLy_procedure_delete ( PLyProcedure proc)
extern

Definition at line 419 of file plpy_procedure.c.

420{
421 Py_XDECREF(proc->code);
422 Py_XDECREF(proc->statics);
423 Py_XDECREF(proc->globals);
425}
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472

References PLyProcedure::code, fb(), PLyProcedure::globals, PLyProcedure::mcxt, MemoryContextDelete(), and PLyProcedure::statics.

Referenced by plpython3_inline_handler(), PLy_procedure_create(), and PLy_procedure_get().

◆ PLy_procedure_get()

PLyProcedure * PLy_procedure_get ( Oid  fn_oid,
Oid  fn_rel,
PLyTrigType  is_trigger 
)
extern

Definition at line 71 of file plpy_procedure.c.

72{
73 bool use_cache;
76 PLyProcedureEntry *volatile entry = NULL;
77 PLyProcedure *volatile proc = NULL;
78 bool found = false;
79
80 if (is_trigger == PLPY_TRIGGER && fn_rel == InvalidOid)
81 use_cache = false;
82 else
83 use_cache = true;
84
87 elog(ERROR, "cache lookup failed for function %u", fn_oid);
88
89 /*
90 * Look for the function in the cache, unless we don't have the necessary
91 * information (e.g. during validation). In that case we just don't cache
92 * anything.
93 */
94 if (use_cache)
95 {
96 key.fn_oid = fn_oid;
97 key.fn_rel = fn_rel;
98 entry = hash_search(PLy_procedure_cache, &key, HASH_ENTER, &found);
99 proc = entry->proc;
100 }
101
102 PG_TRY();
103 {
104 if (!found)
105 {
106 /* Haven't found it, create a new procedure */
107 proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
108 if (use_cache)
109 entry->proc = proc;
110 else
111 {
112 /* Delete the proc, otherwise it's a memory leak */
114 proc = NULL;
115 }
116 }
117 else if (!PLy_procedure_valid(proc, procTup))
118 {
119 /* Found it, but it's invalid, free and reuse the cache entry */
120 entry->proc = NULL;
121 if (proc)
123 proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
124 entry->proc = proc;
125 }
126 /* Found it and it's valid, it's fine to use it */
127 }
128 PG_CATCH();
129 {
130 /* Do not leave an uninitialized entry in the cache */
131 if (use_cache)
133 PG_RE_THROW();
134 }
135 PG_END_TRY();
136
138
139 return proc;
140}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:952
#define PG_RE_THROW()
Definition elog.h:405
#define PG_TRY(...)
Definition elog.h:372
#define PG_END_TRY(...)
Definition elog.h:397
#define PG_CATCH(...)
Definition elog.h:382
@ HASH_REMOVE
Definition hsearch.h:115
@ HASH_ENTER
Definition hsearch.h:114
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static PLyProcedure * PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger)
static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup)
void PLy_procedure_delete(PLyProcedure *proc)
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
#define InvalidOid
PLyProcedure * proc
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition syscache.c:220

References elog, ERROR, fb(), HASH_ENTER, HASH_REMOVE, hash_search(), HeapTupleIsValid, InvalidOid, ObjectIdGetDatum(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLPY_TRIGGER, PLy_procedure_cache, PLy_procedure_create(), PLy_procedure_delete(), PLy_procedure_valid(), PLyProcedureEntry::proc, ReleaseSysCache(), and SearchSysCache1().

Referenced by plpython3_call_handler(), and plpython3_validator().

◆ PLy_procedure_name()

char * PLy_procedure_name ( PLyProcedure proc)
extern

Definition at line 46 of file plpy_procedure.c.

47{
48 if (proc == NULL)
49 return "<unknown procedure>";
50 return proc->proname;
51}

References fb(), and PLyProcedure::proname.

Referenced by plpython_error_callback(), and PLy_traceback().