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