PostgreSQL Source Code  git master
plpy_procedure.c
Go to the documentation of this file.
1 /*
2  * Python procedure manipulation for plpython
3  *
4  * src/pl/plpython/plpy_procedure.c
5  */
6 
7 #include "postgres.h"
8 
9 #include "access/htup_details.h"
10 #include "access/transam.h"
11 #include "funcapi.h"
12 #include "catalog/pg_proc.h"
13 #include "catalog/pg_type.h"
14 #include "utils/builtins.h"
15 #include "utils/hsearch.h"
16 #include "utils/inval.h"
17 #include "utils/lsyscache.h"
18 #include "utils/memutils.h"
19 #include "utils/syscache.h"
20 
21 #include "plpython.h"
22 
23 #include "plpy_procedure.h"
24 
25 #include "plpy_elog.h"
26 #include "plpy_main.h"
27 
28 
29 static HTAB *PLy_procedure_cache = NULL;
30 
31 static PLyProcedure *PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger);
32 static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup);
33 static char *PLy_procedure_munge_source(const char *name, const char *src);
34 
35 
36 void
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 }
47 
48 /*
49  * PLy_procedure_name: get the name of the specified procedure.
50  *
51  * NB: this returns the SQL name, not the internal Python procedure name
52  */
53 char *
55 {
56  if (proc == NULL)
57  return "<unknown procedure>";
58  return proc->proname;
59 }
60 
61 /*
62  * PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
63  * returns a new PLyProcedure.
64  *
65  * fn_oid is the OID of the function requested
66  * fn_rel is InvalidOid or the relation this function triggers on
67  * is_trigger denotes whether the function is a trigger function
68  *
69  * The reason that both fn_rel and is_trigger need to be passed is that when
70  * trigger functions get validated we don't know which relation(s) they'll
71  * be used with, so no sensible fn_rel can be passed.
72  */
74 PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger)
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)
124  hash_search(PLy_procedure_cache, &key, HASH_REMOVE, NULL);
125  PG_RE_THROW();
126  }
127  PG_END_TRY();
128 
129  ReleaseSysCache(procTup);
130 
131  return proc;
132 }
133 
134 /*
135  * Create a new PLyProcedure structure
136  */
137 static PLyProcedure *
138 PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
139 {
140  char procName[NAMEDATALEN + 256];
141  Form_pg_proc procStruct;
142  PLyProcedure *volatile proc;
143  MemoryContext cxt;
144  MemoryContext oldcxt;
145  int rv;
146  char *ptr;
147 
148  procStruct = (Form_pg_proc) GETSTRUCT(procTup);
149  rv = snprintf(procName, sizeof(procName),
150  "__plpython_procedure_%s_%u",
151  NameStr(procStruct->proname),
152  fn_oid);
153  if (rv >= sizeof(procName) || rv < 0)
154  elog(ERROR, "procedure name would overrun buffer");
155 
156  /* Replace any not-legal-in-Python-names characters with '_' */
157  for (ptr = procName; *ptr; ptr++)
158  {
159  if (!((*ptr >= 'A' && *ptr <= 'Z') ||
160  (*ptr >= 'a' && *ptr <= 'z') ||
161  (*ptr >= '0' && *ptr <= '9')))
162  *ptr = '_';
163  }
164 
165  /* Create long-lived context that all procedure info will live in */
167  "PL/Python function",
169 
170  oldcxt = MemoryContextSwitchTo(cxt);
171 
172  proc = (PLyProcedure *) palloc0(sizeof(PLyProcedure));
173  proc->mcxt = cxt;
174 
175  PG_TRY();
176  {
177  Datum protrftypes_datum;
178  Datum prosrcdatum;
179  bool isnull;
180  char *procSource;
181  int i;
182 
183  proc->proname = pstrdup(NameStr(procStruct->proname));
185  proc->pyname = pstrdup(procName);
186  proc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
187  proc->fn_tid = procTup->t_self;
188  proc->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
189  proc->is_setof = procStruct->proretset;
190  proc->is_procedure = (procStruct->prokind == PROKIND_PROCEDURE);
191  proc->src = NULL;
192  proc->argnames = NULL;
193  proc->args = NULL;
194  proc->nargs = 0;
195  proc->langid = procStruct->prolang;
196  protrftypes_datum = SysCacheGetAttr(PROCOID, procTup,
197  Anum_pg_proc_protrftypes,
198  &isnull);
199  proc->trftypes = isnull ? NIL : oid_array_to_list(protrftypes_datum);
200  proc->code = NULL;
201  proc->statics = NULL;
202  proc->globals = NULL;
203  proc->calldepth = 0;
204  proc->argstack = NULL;
205 
206  /*
207  * get information required for output conversion of the return value,
208  * but only if this isn't a trigger.
209  */
210  if (!is_trigger)
211  {
212  Oid rettype = procStruct->prorettype;
213  HeapTuple rvTypeTup;
214  Form_pg_type rvTypeStruct;
215 
216  rvTypeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettype));
217  if (!HeapTupleIsValid(rvTypeTup))
218  elog(ERROR, "cache lookup failed for type %u", rettype);
219  rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);
220 
221  /* Disallow pseudotype result, except for void or record */
222  if (rvTypeStruct->typtype == TYPTYPE_PSEUDO)
223  {
224  if (rettype == VOIDOID ||
225  rettype == RECORDOID)
226  /* okay */ ;
227  else if (rettype == TRIGGEROID || rettype == EVTTRIGGEROID)
228  ereport(ERROR,
229  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
230  errmsg("trigger functions can only be called as triggers")));
231  else
232  ereport(ERROR,
233  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
234  errmsg("PL/Python functions cannot return type %s",
235  format_type_be(rettype))));
236  }
237 
238  /* set up output function for procedure result */
239  PLy_output_setup_func(&proc->result, proc->mcxt,
240  rettype, -1, proc);
241 
242  ReleaseSysCache(rvTypeTup);
243  }
244  else
245  {
246  /*
247  * In a trigger function, we use proc->result and proc->result_in
248  * for converting tuples, but we don't yet have enough info to set
249  * them up. PLy_exec_trigger will deal with it.
250  */
251  proc->result.typoid = InvalidOid;
252  proc->result_in.typoid = InvalidOid;
253  }
254 
255  /*
256  * Now get information required for input conversion of the
257  * procedure's arguments. Note that we ignore output arguments here.
258  * If the function returns record, those I/O functions will be set up
259  * when the function is first called.
260  */
261  if (procStruct->pronargs)
262  {
263  Oid *types;
264  char **names,
265  *modes;
266  int pos,
267  total;
268 
269  /* extract argument type info from the pg_proc tuple */
270  total = get_func_arg_info(procTup, &types, &names, &modes);
271 
272  /* count number of in+inout args into proc->nargs */
273  if (modes == NULL)
274  proc->nargs = total;
275  else
276  {
277  /* proc->nargs was initialized to 0 above */
278  for (i = 0; i < total; i++)
279  {
280  if (modes[i] != PROARGMODE_OUT &&
281  modes[i] != PROARGMODE_TABLE)
282  (proc->nargs)++;
283  }
284  }
285 
286  /* Allocate arrays for per-input-argument data */
287  proc->argnames = (char **) palloc0(sizeof(char *) * proc->nargs);
288  proc->args = (PLyDatumToOb *) palloc0(sizeof(PLyDatumToOb) * proc->nargs);
289 
290  for (i = pos = 0; i < total; i++)
291  {
292  HeapTuple argTypeTup;
293  Form_pg_type argTypeStruct;
294 
295  if (modes &&
296  (modes[i] == PROARGMODE_OUT ||
297  modes[i] == PROARGMODE_TABLE))
298  continue; /* skip OUT arguments */
299 
300  Assert(types[i] == procStruct->proargtypes.values[pos]);
301 
302  argTypeTup = SearchSysCache1(TYPEOID,
303  ObjectIdGetDatum(types[i]));
304  if (!HeapTupleIsValid(argTypeTup))
305  elog(ERROR, "cache lookup failed for type %u", types[i]);
306  argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
307 
308  /* disallow pseudotype arguments */
309  if (argTypeStruct->typtype == TYPTYPE_PSEUDO)
310  ereport(ERROR,
311  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
312  errmsg("PL/Python functions cannot accept type %s",
313  format_type_be(types[i]))));
314 
315  /* set up I/O function info */
316  PLy_input_setup_func(&proc->args[pos], proc->mcxt,
317  types[i], -1, /* typmod not known */
318  proc);
319 
320  /* get argument name */
321  proc->argnames[pos] = names ? pstrdup(names[i]) : NULL;
322 
323  ReleaseSysCache(argTypeTup);
324 
325  pos++;
326  }
327  }
328 
329  /*
330  * get the text of the function.
331  */
332  prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
333  Anum_pg_proc_prosrc, &isnull);
334  if (isnull)
335  elog(ERROR, "null prosrc");
336  procSource = TextDatumGetCString(prosrcdatum);
337 
338  PLy_procedure_compile(proc, procSource);
339 
340  pfree(procSource);
341  }
342  PG_CATCH();
343  {
344  MemoryContextSwitchTo(oldcxt);
345  PLy_procedure_delete(proc);
346  PG_RE_THROW();
347  }
348  PG_END_TRY();
349 
350  MemoryContextSwitchTo(oldcxt);
351  return proc;
352 }
353 
354 /*
355  * Insert the procedure into the Python interpreter
356  */
357 void
358 PLy_procedure_compile(PLyProcedure *proc, const char *src)
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 }
407 
408 void
410 {
411  Py_XDECREF(proc->code);
412  Py_XDECREF(proc->statics);
413  Py_XDECREF(proc->globals);
414  MemoryContextDelete(proc->mcxt);
415 }
416 
417 /*
418  * Decide whether a cached PLyProcedure struct is still valid
419  */
420 static bool
422 {
423  if (proc == NULL)
424  return false;
425 
426  /* If the pg_proc tuple has changed, it's not valid */
427  if (!(proc->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
428  ItemPointerEquals(&proc->fn_tid, &procTup->t_self)))
429  return false;
430 
431  return true;
432 }
433 
434 static char *
435 PLy_procedure_munge_source(const char *name, const char *src)
436 {
437  char *mrc,
438  *mp;
439  const char *sp;
440  size_t mlen;
441  int plen;
442 
443  /*
444  * room for function source and the def statement
445  */
446  mlen = (strlen(src) * 2) + strlen(name) + 16;
447 
448  mrc = palloc(mlen);
449  plen = snprintf(mrc, mlen, "def %s():\n\t", name);
450  Assert(plen >= 0 && plen < mlen);
451 
452  sp = src;
453  mp = mrc + plen;
454 
455  while (*sp != '\0')
456  {
457  if (*sp == '\r' && *(sp + 1) == '\n')
458  sp++;
459 
460  if (*sp == '\n' || *sp == '\r')
461  {
462  *mp++ = '\n';
463  *mp++ = '\t';
464  sp++;
465  }
466  else
467  *mp++ = *sp++;
468  }
469  *mp++ = '\n';
470  *mp++ = '\n';
471  *mp = '\0';
472 
473  if (mp > (mrc + mlen))
474  elog(FATAL, "buffer overrun in PLy_munge_source");
475 
476  return mrc;
477 }
#define NIL
Definition: pg_list.h:69
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
ItemPointerData fn_tid
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
static char * PLy_procedure_munge_source(const char *name, const char *src)
#define HASH_ELEM
Definition: hsearch.h:87
struct typedefs * types
Definition: ecpg.c:29
char * pstrdup(const char *in)
Definition: mcxt.c:1161
void init_procedure_caches(void)
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Definition: funcapi.c:846
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Size entrysize
Definition: hsearch.h:73
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:328
TransactionId fn_xmin
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
unsigned int Oid
Definition: postgres_ext.h:31
PLyDatumToOb * args
HeapTupleHeader t_data
Definition: htup.h:68
#define NAMEDATALEN
List * oid_array_to_list(Datum datum)
Definition: pg_proc.c:1127
char ** argnames
PLyProcedure * PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger)
Definition: dynahash.c:208
void pfree(void *pointer)
Definition: mcxt.c:1031
char * PLy_procedure_name(PLyProcedure *proc)
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
struct PLyProcedureEntry PLyProcedureEntry
MemoryContext mcxt
ItemPointerData t_self
Definition: htup.h:65
#define PLy_elog
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
PyObject * PLy_interp_globals
Definition: plpy_main.c:71
PyObject * statics
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:421
#define ereport(elevel, rest)
Definition: elog.h:122
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup)
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define HASH_BLOBS
Definition: hsearch.h:88
#define TextDatumGetCString(d)
Definition: builtins.h:96
PyObject * code
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Size keysize
Definition: hsearch.h:72
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:132
#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 Assert(condition)
Definition: c.h:699
PLyDatumToOb result_in
FormData_pg_type * Form_pg_type
Definition: pg_type.h:248
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:329
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:307
struct PLyProcedureKey PLyProcedureKey
#define PG_RE_THROW()
Definition: elog.h:314
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
const char * name
Definition: encode.c:521
PLySavedArgs * argstack
PLyProcedure * proc
static HTAB * PLy_procedure_cache
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:299
PLyObToDatum result
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1148
int i
#define NameStr(name)
Definition: c.h:576
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
PyObject * globals
#define PG_END_TRY()
Definition: elog.h:300