PostgreSQL Source Code  git master
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 struct PLySavedArgs PLySavedArgs
 
typedef struct PLyProcedure PLyProcedure
 
typedef struct PLyProcedureKey PLyProcedureKey
 
typedef struct PLyProcedureEntry PLyProcedureEntry
 

Functions

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

Typedef Documentation

◆ PLyProcedure

◆ PLyProcedureEntry

◆ PLyProcedureKey

◆ PLySavedArgs

Function Documentation

◆ init_procedure_caches()

void init_procedure_caches ( void  )

Definition at line 37 of file plpy_procedure.c.

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

Referenced by PLy_initialize().

38 {
39  HASHCTL hash_ctl;
40 
41  memset(&hash_ctl, 0, sizeof(hash_ctl));
42  hash_ctl.keysize = sizeof(PLyProcedureKey);
43  hash_ctl.entrysize = sizeof(PLyProcedureEntry);
44  PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
46 }
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
struct PLyProcedureEntry PLyProcedureEntry
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
struct PLyProcedureKey PLyProcedureKey
static HTAB * PLy_procedure_cache

◆ PLy_procedure_compile()

void PLy_procedure_compile ( PLyProcedure proc,
const char *  src 
)

Definition at line 358 of file plpy_procedure.c.

References PLyProcedure::code, elog, ERROR, 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 plpython_inline_handler(), and PLy_procedure_create().

359 {
360  PyObject *crv = NULL;
361  char *msrc;
362 
363  proc->globals = PyDict_Copy(PLy_interp_globals);
364 
365  /*
366  * SD is private preserved data between calls. GD is global data shared by
367  * all functions
368  */
369  proc->statics = PyDict_New();
370  if (!proc->statics)
371  PLy_elog(ERROR, NULL);
372  PyDict_SetItemString(proc->globals, "SD", proc->statics);
373 
374  /*
375  * insert the function code into the interpreter
376  */
377  msrc = PLy_procedure_munge_source(proc->pyname, src);
378  /* Save the mangled source for later inclusion in tracebacks */
379  proc->src = MemoryContextStrdup(proc->mcxt, msrc);
380  crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
381  pfree(msrc);
382 
383  if (crv != NULL)
384  {
385  int clen;
386  char call[NAMEDATALEN + 256];
387 
388  Py_DECREF(crv);
389 
390  /*
391  * compile a call to the function
392  */
393  clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
394  if (clen < 0 || clen >= sizeof(call))
395  elog(ERROR, "string would overflow buffer");
396  proc->code = Py_CompileString(call, "<string>", Py_eval_input);
397  if (proc->code != NULL)
398  return;
399  }
400 
401  if (proc->proname)
402  PLy_elog(ERROR, "could not compile PL/Python function \"%s\"",
403  proc->proname);
404  else
405  PLy_elog(ERROR, "could not compile anonymous PL/Python code block");
406 }
static char * PLy_procedure_munge_source(const char *name, const char *src)
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
MemoryContext mcxt
#define PLy_elog
PyObject * PLy_interp_globals
Definition: plpy_main.c:71
PyObject * statics
PyObject * code
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1148
#define elog
Definition: elog.h:219
PyObject * globals

◆ PLy_procedure_delete()

void PLy_procedure_delete ( PLyProcedure proc)

Definition at line 409 of file plpy_procedure.c.

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

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

410 {
411  Py_XDECREF(proc->code);
412  Py_XDECREF(proc->statics);
413  Py_XDECREF(proc->globals);
414  MemoryContextDelete(proc->mcxt);
415 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
MemoryContext mcxt
PyObject * statics
PyObject * code
PyObject * globals

◆ PLy_procedure_get()

PLyProcedure* PLy_procedure_get ( Oid  fn_oid,
Oid  fn_rel,
bool  is_trigger 
)

Definition at line 74 of file plpy_procedure.c.

References elog, ERROR, PLyProcedureKey::fn_oid, PLyProcedureKey::fn_rel, HASH_ENTER, HASH_REMOVE, hash_search(), HeapTupleIsValid, InvalidOid, ObjectIdGetDatum, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_procedure_create(), PLy_procedure_delete(), PLy_procedure_valid(), PLyProcedureEntry::proc, PROCOID, ReleaseSysCache(), and SearchSysCache1().

Referenced by plpython_call_handler(), and plpython_validator().

75 {
76  bool use_cache = !(is_trigger && fn_rel == InvalidOid);
77  HeapTuple procTup;
78  PLyProcedureKey key;
79  PLyProcedureEntry *volatile entry = NULL;
80  PLyProcedure *volatile proc = NULL;
81  bool found = false;
82 
83  procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid));
84  if (!HeapTupleIsValid(procTup))
85  elog(ERROR, "cache lookup failed for function %u", fn_oid);
86 
87  /*
88  * Look for the function in the cache, unless we don't have the necessary
89  * information (e.g. during validation). In that case we just don't cache
90  * anything.
91  */
92  if (use_cache)
93  {
94  key.fn_oid = fn_oid;
95  key.fn_rel = fn_rel;
96  entry = hash_search(PLy_procedure_cache, &key, HASH_ENTER, &found);
97  proc = entry->proc;
98  }
99 
100  PG_TRY();
101  {
102  if (!found)
103  {
104  /* Haven't found it, create a new procedure */
105  proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
106  if (use_cache)
107  entry->proc = proc;
108  }
109  else if (!PLy_procedure_valid(proc, procTup))
110  {
111  /* Found it, but it's invalid, free and reuse the cache entry */
112  entry->proc = NULL;
113  if (proc)
114  PLy_procedure_delete(proc);
115  proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
116  entry->proc = proc;
117  }
118  /* Found it and it's valid, it's fine to use it */
119  }
120  PG_CATCH();
121  {
122  /* Do not leave an uninitialized entry in the cache */
123  if (use_cache)
125  PG_RE_THROW();
126  }
127  PG_END_TRY();
128 
129  ReleaseSysCache(procTup);
130 
131  return proc;
132 }
void PLy_procedure_delete(PLyProcedure *proc)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define InvalidOid
Definition: postgres_ext.h:36
static PLyProcedure * PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define PG_RE_THROW()
Definition: elog.h:314
PLyProcedure * proc
static HTAB * PLy_procedure_cache
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300

◆ PLy_procedure_name()

char* PLy_procedure_name ( PLyProcedure proc)

Definition at line 54 of file plpy_procedure.c.

References PLyProcedure::proname.

Referenced by plpython_error_callback(), and PLy_traceback().

55 {
56  if (proc == NULL)
57  return "<unknown procedure>";
58  return proc->proname;
59 }