PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 30 of file plpy_procedure.c.

31 {
32  HASHCTL hash_ctl;
33 
34  hash_ctl.keysize = sizeof(PLyProcedureKey);
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, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
static HTAB * PLy_procedure_cache
struct PLyProcedureKey PLyProcedureKey
struct PLyProcedureEntry PLyProcedureEntry
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76

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

Referenced by PLy_initialize().

◆ PLy_procedure_compile()

void PLy_procedure_compile ( PLyProcedure proc,
const char *  src 
)

Definition at line 349 of file plpy_procedure.c.

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

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 plpython3_inline_handler(), and PLy_procedure_create().

◆ PLy_procedure_delete()

void PLy_procedure_delete ( PLyProcedure proc)

Definition at line 400 of file plpy_procedure.c.

401 {
402  Py_XDECREF(proc->code);
403  Py_XDECREF(proc->statics);
404  Py_XDECREF(proc->globals);
405  MemoryContextDelete(proc->mcxt);
406 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454

References PLyProcedure::code, 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,
bool  is_trigger 
)

Definition at line 66 of file plpy_procedure.c.

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

References elog, ERROR, HASH_ENTER, HASH_REMOVE, hash_search(), HeapTupleIsValid, InvalidOid, sort-test::key, ObjectIdGetDatum(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, 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)

Definition at line 46 of file plpy_procedure.c.

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

References PLyProcedure::proname.

Referenced by plpython_error_callback(), and PLy_traceback().