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

typedef struct PLyProcedure PLyProcedure

◆ PLyProcedureEntry

◆ PLyProcedureKey

◆ PLySavedArgs

typedef struct PLySavedArgs PLySavedArgs

Function Documentation

◆ init_procedure_caches()

void init_procedure_caches ( void  )

Definition at line 33 of file plpy_procedure.c.

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

Referenced by PLy_initialize().

34 {
35  HASHCTL hash_ctl;
36 
37  hash_ctl.keysize = sizeof(PLyProcedureKey);
38  hash_ctl.entrysize = sizeof(PLyProcedureEntry);
39  PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
41 }
#define HASH_ELEM
Definition: hsearch.h:95
Size entrysize
Definition: hsearch.h:76
struct PLyProcedureEntry PLyProcedureEntry
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
#define HASH_BLOBS
Definition: hsearch.h:97
Size keysize
Definition: hsearch.h:75
struct PLyProcedureKey PLyProcedureKey
static HTAB * PLy_procedure_cache

◆ PLy_procedure_compile()

void PLy_procedure_compile ( PLyProcedure proc,
const char *  src 
)

Definition at line 353 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().

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

◆ PLy_procedure_delete()

void PLy_procedure_delete ( PLyProcedure proc)

Definition at line 404 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().

405 {
406  Py_XDECREF(proc->code);
407  Py_XDECREF(proc->statics);
408  Py_XDECREF(proc->globals);
409  MemoryContextDelete(proc->mcxt);
410 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
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 69 of file plpy_procedure.c.

References elog, ERROR, PLyProcedureKey::fn_oid, PLyProcedureKey::fn_rel, HASH_ENTER, HASH_REMOVE, hash_search(), HeapTupleIsValid, InvalidOid, sort-test::key, 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().

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

◆ PLy_procedure_name()

char* PLy_procedure_name ( PLyProcedure proc)

Definition at line 49 of file plpy_procedure.c.

References PLyProcedure::proname.

Referenced by plpython_error_callback(), and PLy_traceback().

50 {
51  if (proc == NULL)
52  return "<unknown procedure>";
53  return proc->proname;
54 }