PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plpy_procedure.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/transam.h"
#include "funcapi.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_proc_fn.h"
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
#include "plpython.h"
#include "plpy_procedure.h"
#include "plpy_elog.h"
#include "plpy_main.h"
Include dependency graph for plpy_procedure.c:

Go to the source code of this file.

Functions

static PLyProcedurePLy_procedure_create (HeapTuple procTup, Oid fn_oid, bool is_trigger)
 
static bool PLy_procedure_argument_valid (PLyTypeInfo *arg)
 
static bool PLy_procedure_valid (PLyProcedure *proc, HeapTuple procTup)
 
static char * PLy_procedure_munge_source (const char *name, const char *src)
 
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)
 

Variables

static HTABPLy_procedure_cache = NULL
 

Function Documentation

void init_procedure_caches ( void  )

Definition at line 38 of file plpy_procedure.c.

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

Referenced by PLy_initialize().

39 {
40  HASHCTL hash_ctl;
41 
42  memset(&hash_ctl, 0, sizeof(hash_ctl));
43  hash_ctl.keysize = sizeof(PLyProcedureKey);
44  hash_ctl.entrysize = sizeof(PLyProcedureEntry);
45  PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
47 }
#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:301
Size keysize
Definition: hsearch.h:72
struct PLyProcedureKey PLyProcedureKey
static HTAB * PLy_procedure_cache
static bool PLy_procedure_argument_valid ( PLyTypeInfo arg)
static

Definition at line 431 of file plpy_procedure.c.

References Assert, elog, ERROR, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, PLyTypeInfo::is_rowtype, ItemPointerEquals(), ItemPointerIsValid, ObjectIdGetDatum, OidIsValid, ReleaseSysCache(), RELOID, SearchSysCache1, HeapTupleData::t_data, HeapTupleData::t_self, TransactionIdIsValid, PLyTypeInfo::typ_relid, PLyTypeInfo::typrel_tid, and PLyTypeInfo::typrel_xmin.

Referenced by PLy_procedure_valid().

432 {
433  HeapTuple relTup;
434  bool valid;
435 
436  /* Nothing to cache unless type is composite */
437  if (arg->is_rowtype != 1)
438  return true;
439 
440  /*
441  * Zero typ_relid means that we got called on an output argument of a
442  * function returning an unnamed record type; the info for it can't
443  * change.
444  */
445  if (!OidIsValid(arg->typ_relid))
446  return true;
447 
448  /* Else we should have some cached data */
451 
452  /* Get the pg_class tuple for the data type */
454  if (!HeapTupleIsValid(relTup))
455  elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);
456 
457  /* If it has changed, the cached data is not valid */
458  valid = (arg->typrel_xmin == HeapTupleHeaderGetRawXmin(relTup->t_data) &&
459  ItemPointerEquals(&arg->typrel_tid, &relTup->t_self));
460 
461  ReleaseSysCache(relTup);
462 
463  return valid;
464 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:59
TransactionId typrel_xmin
Definition: plpy_typeio.h:96
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
HeapTupleHeader t_data
Definition: htup.h:67
ItemPointerData typrel_tid
Definition: plpy_typeio.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:675
int is_rowtype
Definition: plpy_typeio.h:93
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void PLy_procedure_compile ( PLyProcedure proc,
const char *  src 
)

Definition at line 370 of file plpy_procedure.c.

References PLyProcedure::code, elog, ERROR, PLyProcedure::globals, PLyProcedure::mcxt, MemoryContextStrdup(), NAMEDATALEN, NULL, 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().

371 {
372  PyObject *crv = NULL;
373  char *msrc;
374 
375  proc->globals = PyDict_Copy(PLy_interp_globals);
376 
377  /*
378  * SD is private preserved data between calls. GD is global data shared by
379  * all functions
380  */
381  proc->statics = PyDict_New();
382  PyDict_SetItemString(proc->globals, "SD", proc->statics);
383 
384  /*
385  * insert the function code into the interpreter
386  */
387  msrc = PLy_procedure_munge_source(proc->pyname, src);
388  /* Save the mangled source for later inclusion in tracebacks */
389  proc->src = MemoryContextStrdup(proc->mcxt, msrc);
390  crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
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 }
static char * PLy_procedure_munge_source(const char *name, const char *src)
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define NAMEDATALEN
void pfree(void *pointer)
Definition: mcxt.c:950
#define ERROR
Definition: elog.h:43
MemoryContext mcxt
PyObject * PLy_interp_globals
Definition: plpy_main.c:71
PyObject * statics
PyObject * code
#define NULL
Definition: c.h:229
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1064
#define elog
Definition: elog.h:219
PyObject * globals
static PLyProcedure * PLy_procedure_create ( HeapTuple  procTup,
Oid  fn_oid,
bool  is_trigger 
)
static

Definition at line 141 of file plpy_procedure.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Anum_pg_proc_prosrc, Anum_pg_proc_protrftypes, PLyProcedure::argnames, PLyProcedure::args, PLyProcedure::argstack, Assert, PLyProcedure::calldepth, PLyProcedure::code, PLyTypeOutput::d, elog, ereport, errcode(), errmsg(), ERROR, PLyProcedure::fn_readonly, PLyProcedure::fn_tid, PLyProcedure::fn_xmin, format_type_be(), FUNC_MAX_ARGS, get_func_arg_info(), GETSTRUCT, PLyProcedure::globals, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, i, PLyTypeInfo::is_rowtype, PLyProcedure::is_setof, PLyProcedure::langid, PLyProcedure::mcxt, MemoryContextSwitchTo(), NAMEDATALEN, NameStr, PLyProcedure::nargs, NIL, NULL, ObjectIdGetDatum, oid_array_to_list(), PLyTypeInfo::out, palloc0(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_input_datum_func(), PLy_output_datum_func(), PLy_procedure_compile(), PLy_procedure_delete(), PLy_typeinfo_init(), PROARGMODE_OUT, PROARGMODE_TABLE, PROCOID, PLyProcedure::proname, PROVOLATILE_VOLATILE, pstrdup(), PLyProcedure::pyname, RECORDOID, ReleaseSysCache(), PLyProcedure::result, SearchSysCache1, snprintf(), PLyProcedure::src, PLyProcedure::statics, SysCacheGetAttr(), HeapTupleData::t_data, HeapTupleData::t_self, TextDatumGetCString, TopMemoryContext, PLyProcedure::trftypes, TRIGGEROID, TYPEOID, types, PLyObToDatum::typmod, PLyObToDatum::typoid, TYPTYPE_COMPOSITE, TYPTYPE_PSEUDO, and VOIDOID.

Referenced by PLy_procedure_get().

142 {
143  char procName[NAMEDATALEN + 256];
144  Form_pg_proc procStruct;
145  PLyProcedure *volatile proc;
146  MemoryContext cxt;
147  MemoryContext oldcxt;
148  int rv;
149  char *ptr;
150 
151  procStruct = (Form_pg_proc) GETSTRUCT(procTup);
152  rv = snprintf(procName, sizeof(procName),
153  "__plpython_procedure_%s_%u",
154  NameStr(procStruct->proname),
155  fn_oid);
156  if (rv >= sizeof(procName) || rv < 0)
157  elog(ERROR, "procedure name would overrun buffer");
158 
159  /* Replace any not-legal-in-Python-names characters with '_' */
160  for (ptr = procName; *ptr; ptr++)
161  {
162  if (!((*ptr >= 'A' && *ptr <= 'Z') ||
163  (*ptr >= 'a' && *ptr <= 'z') ||
164  (*ptr >= '0' && *ptr <= '9')))
165  *ptr = '_';
166  }
167 
169  procName,
171 
172  oldcxt = MemoryContextSwitchTo(cxt);
173 
174  proc = (PLyProcedure *) palloc0(sizeof(PLyProcedure));
175  proc->mcxt = cxt;
176 
177  PG_TRY();
178  {
179  Datum protrftypes_datum;
180  Datum prosrcdatum;
181  bool isnull;
182  char *procSource;
183  int i;
184 
185  proc->proname = pstrdup(NameStr(procStruct->proname));
186  proc->pyname = pstrdup(procName);
187  proc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
188  proc->fn_tid = procTup->t_self;
189  proc->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
190  proc->is_setof = procStruct->proretset;
191  PLy_typeinfo_init(&proc->result, proc->mcxt);
192  proc->src = NULL;
193  proc->argnames = NULL;
194  for (i = 0; i < FUNC_MAX_ARGS; i++)
195  PLy_typeinfo_init(&proc->args[i], proc->mcxt);
196  proc->nargs = 0;
197  proc->langid = procStruct->prolang;
198  protrftypes_datum = SysCacheGetAttr(PROCOID, procTup,
200  &isnull);
201  proc->trftypes = isnull ? NIL : oid_array_to_list(protrftypes_datum);
202  proc->code = NULL;
203  proc->statics = NULL;
204  proc->globals = NULL;
205  proc->calldepth = 0;
206  proc->argstack = NULL;
207 
208  /*
209  * get information required for output conversion of the return value,
210  * but only if this isn't a trigger.
211  */
212  if (!is_trigger)
213  {
214  HeapTuple rvTypeTup;
215  Form_pg_type rvTypeStruct;
216 
217  rvTypeTup = SearchSysCache1(TYPEOID,
218  ObjectIdGetDatum(procStruct->prorettype));
219  if (!HeapTupleIsValid(rvTypeTup))
220  elog(ERROR, "cache lookup failed for type %u",
221  procStruct->prorettype);
222  rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);
223 
224  /* Disallow pseudotype result, except for void or record */
225  if (rvTypeStruct->typtype == TYPTYPE_PSEUDO)
226  {
227  if (procStruct->prorettype == TRIGGEROID)
228  ereport(ERROR,
229  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
230  errmsg("trigger functions can only be called as triggers")));
231  else if (procStruct->prorettype != VOIDOID &&
232  procStruct->prorettype != RECORDOID)
233  ereport(ERROR,
234  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
235  errmsg("PL/Python functions cannot return type %s",
236  format_type_be(procStruct->prorettype))));
237  }
238 
239  if (rvTypeStruct->typtype == TYPTYPE_COMPOSITE ||
240  procStruct->prorettype == RECORDOID)
241  {
242  /*
243  * Tuple: set up later, during first call to
244  * PLy_function_handler
245  */
246  proc->result.out.d.typoid = procStruct->prorettype;
247  proc->result.out.d.typmod = -1;
248  proc->result.is_rowtype = 2;
249  }
250  else
251  {
252  /* do the real work */
253  PLy_output_datum_func(&proc->result, rvTypeTup, proc->langid, proc->trftypes);
254  }
255 
256  ReleaseSysCache(rvTypeTup);
257  }
258 
259  /*
260  * Now get information required for input conversion of the
261  * procedure's arguments. Note that we ignore output arguments here.
262  * If the function returns record, those I/O functions will be set up
263  * when the function is first called.
264  */
265  if (procStruct->pronargs)
266  {
267  Oid *types;
268  char **names,
269  *modes;
270  int pos,
271  total;
272 
273  /* extract argument type info from the pg_proc tuple */
274  total = get_func_arg_info(procTup, &types, &names, &modes);
275 
276  /* count number of in+inout args into proc->nargs */
277  if (modes == NULL)
278  proc->nargs = total;
279  else
280  {
281  /* proc->nargs was initialized to 0 above */
282  for (i = 0; i < total; i++)
283  {
284  if (modes[i] != PROARGMODE_OUT &&
285  modes[i] != PROARGMODE_TABLE)
286  (proc->nargs)++;
287  }
288  }
289 
290  proc->argnames = (char **) palloc0(sizeof(char *) * proc->nargs);
291  for (i = pos = 0; i < total; i++)
292  {
293  HeapTuple argTypeTup;
294  Form_pg_type argTypeStruct;
295 
296  if (modes &&
297  (modes[i] == PROARGMODE_OUT ||
298  modes[i] == PROARGMODE_TABLE))
299  continue; /* skip OUT arguments */
300 
301  Assert(types[i] == procStruct->proargtypes.values[pos]);
302 
303  argTypeTup = SearchSysCache1(TYPEOID,
304  ObjectIdGetDatum(types[i]));
305  if (!HeapTupleIsValid(argTypeTup))
306  elog(ERROR, "cache lookup failed for type %u", types[i]);
307  argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
308 
309  /* check argument type is OK, set up I/O function info */
310  switch (argTypeStruct->typtype)
311  {
312  case TYPTYPE_PSEUDO:
313  /* Disallow pseudotype argument */
314  ereport(ERROR,
315  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
316  errmsg("PL/Python functions cannot accept type %s",
317  format_type_be(types[i]))));
318  break;
319  case TYPTYPE_COMPOSITE:
320  /* we'll set IO funcs at first call */
321  proc->args[pos].is_rowtype = 2;
322  break;
323  default:
324  PLy_input_datum_func(&(proc->args[pos]),
325  types[i],
326  argTypeTup,
327  proc->langid,
328  proc->trftypes);
329  break;
330  }
331 
332  /* get argument name */
333  proc->argnames[pos] = names ? pstrdup(names[i]) : NULL;
334 
335  ReleaseSysCache(argTypeTup);
336 
337  pos++;
338  }
339  }
340 
341  /*
342  * get the text of the function.
343  */
344  prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
345  Anum_pg_proc_prosrc, &isnull);
346  if (isnull)
347  elog(ERROR, "null prosrc");
348  procSource = TextDatumGetCString(prosrcdatum);
349 
350  PLy_procedure_compile(proc, procSource);
351 
352  pfree(procSource);
353  }
354  PG_CATCH();
355  {
356  MemoryContextSwitchTo(oldcxt);
357  PLy_procedure_delete(proc);
358  PG_RE_THROW();
359  }
360  PG_END_TRY();
361 
362  MemoryContextSwitchTo(oldcxt);
363  return proc;
364 }
#define NIL
Definition: pg_list.h:69
ItemPointerData fn_tid
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void PLy_input_datum_func(PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:87
void PLy_typeinfo_init(PLyTypeInfo *arg, MemoryContext mcxt)
Definition: plpy_typeio.c:70
PLyTypeInfo args[FUNC_MAX_ARGS]
struct typedefs * types
Definition: ecpg.c:29
void PLy_output_datum_func(PLyTypeInfo *arg, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:96
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
char * pstrdup(const char *in)
Definition: mcxt.c:1077
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:791
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Anum_pg_proc_prosrc
Definition: pg_proc.h:115
void PLy_procedure_delete(PLyProcedure *proc)
int errcode(int sqlerrcode)
Definition: elog.c:575
void PLy_procedure_compile(PLyProcedure *proc, const char *src)
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define Anum_pg_proc_protrftypes
Definition: pg_proc.h:114
TransactionId fn_xmin
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
int32 typmod
Definition: plpy_typeio.h:61
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
#define PROARGMODE_OUT
Definition: pg_proc.h:5502
HeapTupleHeader t_data
Definition: htup.h:67
#define FUNC_MAX_ARGS
#define NAMEDATALEN
List * oid_array_to_list(Datum datum)
Definition: pg_proc.c:1156
char ** argnames
PLyTypeInfo result
void pfree(void *pointer)
Definition: mcxt.c:950
#define VOIDOID
Definition: pg_type.h:690
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
PLyObToDatum d
Definition: plpy_typeio.h:77
#define TRIGGEROID
Definition: pg_type.h:692
#define PROARGMODE_TABLE
Definition: pg_proc.h:5505
MemoryContext mcxt
ItemPointerData t_self
Definition: htup.h:65
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
PLyTypeOutput out
Definition: plpy_typeio.h:87
PyObject * statics
#define RECORDOID
Definition: pg_type.h:680
#define ereport(elevel, rest)
Definition: elog.h:122
MemoryContext TopMemoryContext
Definition: mcxt.c:43
#define PROVOLATILE_VOLATILE
Definition: pg_proc.h:5485
#define TextDatumGetCString(d)
Definition: builtins.h:92
PyObject * code
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:878
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
int is_rowtype
Definition: plpy_typeio.h:93
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
#define PG_RE_THROW()
Definition: elog.h:314
PLySavedArgs * argstack
#define TYPTYPE_PSEUDO
Definition: pg_type.h:724
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
PyObject * globals
#define PG_END_TRY()
Definition: elog.h:300
void PLy_procedure_delete ( PLyProcedure proc)

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

420 {
421  Py_XDECREF(proc->code);
422  Py_XDECREF(proc->statics);
423  Py_XDECREF(proc->globals);
424  MemoryContextDelete(proc->mcxt);
425 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
MemoryContext mcxt
PyObject * statics
PyObject * code
PyObject * globals
PLyProcedure* PLy_procedure_get ( Oid  fn_oid,
Oid  fn_rel,
bool  is_trigger 
)

Definition at line 77 of file plpy_procedure.c.

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

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

Definition at line 502 of file plpy_procedure.c.

References Assert, elog, FATAL, palloc(), and snprintf().

Referenced by PLy_procedure_compile().

503 {
504  char *mrc,
505  *mp;
506  const char *sp;
507  size_t mlen;
508  int plen;
509 
510  /*
511  * room for function source and the def statement
512  */
513  mlen = (strlen(src) * 2) + strlen(name) + 16;
514 
515  mrc = palloc(mlen);
516  plen = snprintf(mrc, mlen, "def %s():\n\t", name);
517  Assert(plen >= 0 && plen < mlen);
518 
519  sp = src;
520  mp = mrc + plen;
521 
522  while (*sp != '\0')
523  {
524  if (*sp == '\r' && *(sp + 1) == '\n')
525  sp++;
526 
527  if (*sp == '\n' || *sp == '\r')
528  {
529  *mp++ = '\n';
530  *mp++ = '\t';
531  sp++;
532  }
533  else
534  *mp++ = *sp++;
535  }
536  *mp++ = '\n';
537  *mp++ = '\n';
538  *mp = '\0';
539 
540  if (mp > (mrc + mlen))
541  elog(FATAL, "buffer overrun in PLy_munge_source");
542 
543  return mrc;
544 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define FATAL
Definition: elog.h:52
#define Assert(condition)
Definition: c.h:675
const char * name
Definition: encode.c:521
void * palloc(Size size)
Definition: mcxt.c:849
#define elog
Definition: elog.h:219
char* PLy_procedure_name ( PLyProcedure proc)

Definition at line 57 of file plpy_procedure.c.

References NULL, and PLyProcedure::proname.

Referenced by plpython_error_callback(), and PLy_traceback().

58 {
59  if (proc == NULL)
60  return "<unknown procedure>";
61  return proc->proname;
62 }
#define NULL
Definition: c.h:229
static bool PLy_procedure_valid ( PLyProcedure proc,
HeapTuple  procTup 
)
static

Definition at line 470 of file plpy_procedure.c.

References PLyProcedure::args, PLyProcedure::fn_tid, PLyProcedure::fn_xmin, HeapTupleHeaderGetRawXmin, i, ItemPointerEquals(), PLyProcedure::nargs, NULL, PLy_procedure_argument_valid(), PLyProcedure::result, HeapTupleData::t_data, and HeapTupleData::t_self.

Referenced by PLy_procedure_get().

471 {
472  int i;
473  bool valid;
474 
475  if (proc == NULL)
476  return false;
477 
478  /* If the pg_proc tuple has changed, it's not valid */
479  if (!(proc->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
480  ItemPointerEquals(&proc->fn_tid, &procTup->t_self)))
481  return false;
482 
483  /* Else check the input argument datatypes */
484  valid = true;
485  for (i = 0; i < proc->nargs; i++)
486  {
487  valid = PLy_procedure_argument_valid(&proc->args[i]);
488 
489  /* Short-circuit on first changed argument */
490  if (!valid)
491  break;
492  }
493 
494  /* if the output type is composite, it might have changed */
495  if (valid)
496  valid = PLy_procedure_argument_valid(&proc->result);
497 
498  return valid;
499 }
ItemPointerData fn_tid
PLyTypeInfo args[FUNC_MAX_ARGS]
TransactionId fn_xmin
HeapTupleHeader t_data
Definition: htup.h:67
PLyTypeInfo result
ItemPointerData t_self
Definition: htup.h:65
static bool PLy_procedure_argument_valid(PLyTypeInfo *arg)
#define NULL
Definition: c.h:229
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
int i

Variable Documentation

HTAB* PLy_procedure_cache = NULL
static

Definition at line 29 of file plpy_procedure.c.