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