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  memset(&hash_ctl, 0, sizeof(hash_ctl));
38  hash_ctl.keysize = sizeof(PLyProcedureKey);
39  hash_ctl.entrysize = sizeof(PLyProcedureEntry);
40  PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
42 }
#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 354 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().

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

◆ PLy_procedure_delete()

void PLy_procedure_delete ( PLyProcedure proc)

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

406 {
407  Py_XDECREF(proc->code);
408  Py_XDECREF(proc->statics);
409  Py_XDECREF(proc->globals);
410  MemoryContextDelete(proc->mcxt);
411 }
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 70 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().

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

◆ PLy_procedure_name()

char* PLy_procedure_name ( PLyProcedure proc)

Definition at line 50 of file plpy_procedure.c.

References PLyProcedure::proname.

Referenced by plpython_error_callback(), and PLy_traceback().

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