Line data Source code
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 "catalog/pg_proc.h"
11 : #include "catalog/pg_type.h"
12 : #include "funcapi.h"
13 : #include "plpy_elog.h"
14 : #include "plpy_main.h"
15 : #include "plpy_procedure.h"
16 : #include "plpy_util.h"
17 : #include "utils/builtins.h"
18 : #include "utils/hsearch.h"
19 : #include "utils/memutils.h"
20 : #include "utils/syscache.h"
21 :
22 : static HTAB *PLy_procedure_cache = NULL;
23 :
24 : static PLyProcedure *PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger);
25 : static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup);
26 : static char *PLy_procedure_munge_source(const char *name, const char *src);
27 :
28 :
29 : void
30 46 : init_procedure_caches(void)
31 : {
32 : HASHCTL hash_ctl;
33 :
34 46 : hash_ctl.keysize = sizeof(PLyProcedureKey);
35 46 : hash_ctl.entrysize = sizeof(PLyProcedureEntry);
36 46 : PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
37 : HASH_ELEM | HASH_BLOBS);
38 46 : }
39 :
40 : /*
41 : * PLy_procedure_name: get the name of the specified procedure.
42 : *
43 : * NB: this returns the SQL name, not the internal Python procedure name
44 : */
45 : char *
46 1062 : PLy_procedure_name(PLyProcedure *proc)
47 : {
48 1062 : if (proc == NULL)
49 0 : return "<unknown procedure>";
50 1062 : return proc->proname;
51 : }
52 :
53 : /*
54 : * PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
55 : * returns a new PLyProcedure.
56 : *
57 : * fn_oid is the OID of the function requested
58 : * fn_rel is InvalidOid or the relation this function triggers on
59 : * is_trigger denotes whether the function is a trigger function
60 : *
61 : * The reason that both fn_rel and is_trigger need to be passed is that when
62 : * trigger functions get validated we don't know which relation(s) they'll
63 : * be used with, so no sensible fn_rel can be passed. Also, in that case
64 : * we can't make a cache entry because we can't construct the right cache key.
65 : * To forestall leakage of the PLyProcedure in such cases, delete it after
66 : * construction and return NULL. That's okay because the only caller that
67 : * would pass that set of values is plpython3_validator, which ignores our
68 : * result anyway.
69 : */
70 : PLyProcedure *
71 1902 : PLy_procedure_get(Oid fn_oid, Oid fn_rel, PLyTrigType is_trigger)
72 : {
73 : bool use_cache;
74 : HeapTuple procTup;
75 : PLyProcedureKey key;
76 1902 : PLyProcedureEntry *volatile entry = NULL;
77 1902 : PLyProcedure *volatile proc = NULL;
78 1902 : bool found = false;
79 :
80 1902 : if (is_trigger == PLPY_TRIGGER && fn_rel == InvalidOid)
81 48 : use_cache = false;
82 : else
83 1854 : use_cache = true;
84 :
85 1902 : procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid));
86 1902 : if (!HeapTupleIsValid(procTup))
87 0 : elog(ERROR, "cache lookup failed for function %u", fn_oid);
88 :
89 : /*
90 : * Look for the function in the cache, unless we don't have the necessary
91 : * information (e.g. during validation). In that case we just don't cache
92 : * anything.
93 : */
94 1902 : if (use_cache)
95 : {
96 1854 : key.fn_oid = fn_oid;
97 1854 : key.fn_rel = fn_rel;
98 1854 : entry = hash_search(PLy_procedure_cache, &key, HASH_ENTER, &found);
99 1854 : proc = entry->proc;
100 : }
101 :
102 1902 : PG_TRY();
103 : {
104 1902 : if (!found)
105 : {
106 : /* Haven't found it, create a new procedure */
107 548 : proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
108 540 : if (use_cache)
109 492 : entry->proc = proc;
110 : else
111 : {
112 : /* Delete the proc, otherwise it's a memory leak */
113 48 : PLy_procedure_delete(proc);
114 48 : proc = NULL;
115 : }
116 : }
117 1354 : else if (!PLy_procedure_valid(proc, procTup))
118 : {
119 : /* Found it, but it's invalid, free and reuse the cache entry */
120 10 : entry->proc = NULL;
121 10 : if (proc)
122 10 : PLy_procedure_delete(proc);
123 10 : proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
124 10 : entry->proc = proc;
125 : }
126 : /* Found it and it's valid, it's fine to use it */
127 : }
128 8 : PG_CATCH();
129 : {
130 : /* Do not leave an uninitialized entry in the cache */
131 8 : if (use_cache)
132 8 : hash_search(PLy_procedure_cache, &key, HASH_REMOVE, NULL);
133 8 : PG_RE_THROW();
134 : }
135 1894 : PG_END_TRY();
136 :
137 1894 : ReleaseSysCache(procTup);
138 :
139 1894 : return proc;
140 : }
141 :
142 : /*
143 : * Create a new PLyProcedure structure
144 : */
145 : static PLyProcedure *
146 558 : PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger)
147 : {
148 : char procName[NAMEDATALEN + 256];
149 : Form_pg_proc procStruct;
150 : PLyProcedure *volatile proc;
151 : MemoryContext cxt;
152 : MemoryContext oldcxt;
153 : int rv;
154 : char *ptr;
155 :
156 558 : procStruct = (Form_pg_proc) GETSTRUCT(procTup);
157 1116 : rv = snprintf(procName, sizeof(procName),
158 : "__plpython_procedure_%s_%u",
159 558 : NameStr(procStruct->proname),
160 : fn_oid);
161 558 : if (rv >= sizeof(procName) || rv < 0)
162 0 : elog(ERROR, "procedure name would overrun buffer");
163 :
164 : /* Replace any not-legal-in-Python-names characters with '_' */
165 26134 : for (ptr = procName; *ptr; ptr++)
166 : {
167 25576 : if (!((*ptr >= 'A' && *ptr <= 'Z') ||
168 25574 : (*ptr >= 'a' && *ptr <= 'z') ||
169 6854 : (*ptr >= '0' && *ptr <= '9')))
170 3860 : *ptr = '_';
171 : }
172 :
173 : /* Create long-lived context that all procedure info will live in */
174 558 : cxt = AllocSetContextCreate(TopMemoryContext,
175 : "PL/Python function",
176 : ALLOCSET_DEFAULT_SIZES);
177 :
178 558 : oldcxt = MemoryContextSwitchTo(cxt);
179 :
180 558 : proc = (PLyProcedure *) palloc0(sizeof(PLyProcedure));
181 558 : proc->mcxt = cxt;
182 :
183 558 : PG_TRY();
184 : {
185 : Datum protrftypes_datum;
186 : Datum prosrcdatum;
187 : bool isnull;
188 : char *procSource;
189 : int i;
190 :
191 558 : proc->proname = pstrdup(NameStr(procStruct->proname));
192 558 : MemoryContextSetIdentifier(cxt, proc->proname);
193 558 : proc->pyname = pstrdup(procName);
194 558 : proc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
195 558 : proc->fn_tid = procTup->t_self;
196 558 : proc->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
197 558 : proc->is_setof = procStruct->proretset;
198 558 : proc->is_procedure = (procStruct->prokind == PROKIND_PROCEDURE);
199 558 : proc->is_trigger = is_trigger;
200 558 : proc->src = NULL;
201 558 : proc->argnames = NULL;
202 558 : proc->args = NULL;
203 558 : proc->nargs = 0;
204 558 : proc->langid = procStruct->prolang;
205 558 : protrftypes_datum = SysCacheGetAttr(PROCOID, procTup,
206 : Anum_pg_proc_protrftypes,
207 : &isnull);
208 558 : proc->trftypes = isnull ? NIL : oid_array_to_list(protrftypes_datum);
209 558 : proc->code = NULL;
210 558 : proc->statics = NULL;
211 558 : proc->globals = NULL;
212 558 : proc->calldepth = 0;
213 558 : proc->argstack = NULL;
214 :
215 : /*
216 : * get information required for output conversion of the return value,
217 : * but only if this isn't a trigger.
218 : */
219 558 : if (is_trigger == PLPY_NOT_TRIGGER)
220 : {
221 456 : Oid rettype = procStruct->prorettype;
222 : HeapTuple rvTypeTup;
223 : Form_pg_type rvTypeStruct;
224 :
225 456 : rvTypeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettype));
226 456 : if (!HeapTupleIsValid(rvTypeTup))
227 0 : elog(ERROR, "cache lookup failed for type %u", rettype);
228 456 : rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);
229 :
230 : /* Disallow pseudotype result, except for void or record */
231 456 : if (rvTypeStruct->typtype == TYPTYPE_PSEUDO)
232 : {
233 104 : if (rettype == VOIDOID ||
234 : rettype == RECORDOID)
235 : /* okay */ ;
236 2 : else if (rettype == TRIGGEROID || rettype == EVENT_TRIGGEROID)
237 2 : ereport(ERROR,
238 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
239 : errmsg("trigger functions can only be called as triggers")));
240 : else
241 0 : ereport(ERROR,
242 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
243 : errmsg("PL/Python functions cannot return type %s",
244 : format_type_be(rettype))));
245 : }
246 :
247 : /* set up output function for procedure result */
248 454 : PLy_output_setup_func(&proc->result, proc->mcxt,
249 : rettype, -1, proc);
250 :
251 454 : ReleaseSysCache(rvTypeTup);
252 : }
253 : else
254 : {
255 : /*
256 : * In a trigger function, we use proc->result and proc->result_in
257 : * for converting tuples, but we don't yet have enough info to set
258 : * them up. PLy_exec_trigger will deal with it.
259 : */
260 102 : proc->result.typoid = InvalidOid;
261 102 : proc->result_in.typoid = InvalidOid;
262 : }
263 :
264 : /*
265 : * Now get information required for input conversion of the
266 : * procedure's arguments. Note that we ignore output arguments here.
267 : * If the function returns record, those I/O functions will be set up
268 : * when the function is first called.
269 : */
270 556 : if (procStruct->pronargs)
271 : {
272 : Oid *types;
273 : char **names,
274 : *modes;
275 : int pos,
276 : total;
277 :
278 : /* extract argument type info from the pg_proc tuple */
279 214 : total = get_func_arg_info(procTup, &types, &names, &modes);
280 :
281 : /* count number of in+inout args into proc->nargs */
282 214 : if (modes == NULL)
283 192 : proc->nargs = total;
284 : else
285 : {
286 : /* proc->nargs was initialized to 0 above */
287 82 : for (i = 0; i < total; i++)
288 : {
289 60 : if (modes[i] != PROARGMODE_OUT &&
290 36 : modes[i] != PROARGMODE_TABLE)
291 36 : (proc->nargs)++;
292 : }
293 : }
294 :
295 : /* Allocate arrays for per-input-argument data */
296 214 : proc->argnames = (char **) palloc0(sizeof(char *) * proc->nargs);
297 214 : proc->args = (PLyDatumToOb *) palloc0(sizeof(PLyDatumToOb) * proc->nargs);
298 :
299 554 : for (i = pos = 0; i < total; i++)
300 : {
301 : HeapTuple argTypeTup;
302 : Form_pg_type argTypeStruct;
303 :
304 340 : if (modes &&
305 60 : (modes[i] == PROARGMODE_OUT ||
306 36 : modes[i] == PROARGMODE_TABLE))
307 24 : continue; /* skip OUT arguments */
308 :
309 : Assert(types[i] == procStruct->proargtypes.values[pos]);
310 :
311 316 : argTypeTup = SearchSysCache1(TYPEOID,
312 316 : ObjectIdGetDatum(types[i]));
313 316 : if (!HeapTupleIsValid(argTypeTup))
314 0 : elog(ERROR, "cache lookup failed for type %u", types[i]);
315 316 : argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
316 :
317 : /* disallow pseudotype arguments */
318 316 : if (argTypeStruct->typtype == TYPTYPE_PSEUDO)
319 0 : ereport(ERROR,
320 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
321 : errmsg("PL/Python functions cannot accept type %s",
322 : format_type_be(types[i]))));
323 :
324 : /* set up I/O function info */
325 316 : PLy_input_setup_func(&proc->args[pos], proc->mcxt,
326 316 : types[i], -1, /* typmod not known */
327 : proc);
328 :
329 : /* get argument name */
330 316 : proc->argnames[pos] = names ? pstrdup(names[i]) : NULL;
331 :
332 316 : ReleaseSysCache(argTypeTup);
333 :
334 316 : pos++;
335 : }
336 : }
337 :
338 : /*
339 : * get the text of the function.
340 : */
341 556 : prosrcdatum = SysCacheGetAttrNotNull(PROCOID, procTup,
342 : Anum_pg_proc_prosrc);
343 556 : procSource = TextDatumGetCString(prosrcdatum);
344 :
345 556 : PLy_procedure_compile(proc, procSource);
346 :
347 550 : pfree(procSource);
348 : }
349 8 : PG_CATCH();
350 : {
351 8 : MemoryContextSwitchTo(oldcxt);
352 8 : PLy_procedure_delete(proc);
353 8 : PG_RE_THROW();
354 : }
355 550 : PG_END_TRY();
356 :
357 550 : MemoryContextSwitchTo(oldcxt);
358 550 : return proc;
359 : }
360 :
361 : /*
362 : * Insert the procedure into the Python interpreter
363 : */
364 : void
365 598 : PLy_procedure_compile(PLyProcedure *proc, const char *src)
366 : {
367 598 : PyObject *crv = NULL;
368 : char *msrc;
369 : PyObject *code0;
370 :
371 598 : proc->globals = PyDict_Copy(PLy_interp_globals);
372 :
373 : /*
374 : * SD is private preserved data between calls. GD is global data shared by
375 : * all functions
376 : */
377 598 : proc->statics = PyDict_New();
378 598 : if (!proc->statics)
379 0 : PLy_elog(ERROR, NULL);
380 598 : PyDict_SetItemString(proc->globals, "SD", proc->statics);
381 :
382 : /*
383 : * insert the function code into the interpreter
384 : */
385 598 : msrc = PLy_procedure_munge_source(proc->pyname, src);
386 : /* Save the mangled source for later inclusion in tracebacks */
387 598 : proc->src = MemoryContextStrdup(proc->mcxt, msrc);
388 598 : code0 = Py_CompileString(msrc, "<string>", Py_file_input);
389 598 : if (code0)
390 592 : crv = PyEval_EvalCode(code0, proc->globals, NULL);
391 598 : pfree(msrc);
392 :
393 598 : if (crv != NULL)
394 : {
395 : int clen;
396 : char call[NAMEDATALEN + 256];
397 :
398 592 : Py_DECREF(crv);
399 :
400 : /*
401 : * compile a call to the function
402 : */
403 592 : clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
404 592 : if (clen < 0 || clen >= sizeof(call))
405 0 : elog(ERROR, "string would overflow buffer");
406 592 : proc->code = Py_CompileString(call, "<string>", Py_eval_input);
407 592 : if (proc->code != NULL)
408 592 : return;
409 : }
410 :
411 6 : if (proc->proname)
412 6 : PLy_elog(ERROR, "could not compile PL/Python function \"%s\"",
413 : proc->proname);
414 : else
415 0 : PLy_elog(ERROR, "could not compile anonymous PL/Python code block");
416 : }
417 :
418 : void
419 108 : PLy_procedure_delete(PLyProcedure *proc)
420 : {
421 108 : Py_XDECREF(proc->code);
422 108 : Py_XDECREF(proc->statics);
423 108 : Py_XDECREF(proc->globals);
424 108 : MemoryContextDelete(proc->mcxt);
425 108 : }
426 :
427 : /*
428 : * Decide whether a cached PLyProcedure struct is still valid
429 : */
430 : static bool
431 1354 : PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup)
432 : {
433 1354 : if (proc == NULL)
434 0 : return false;
435 :
436 : /* If the pg_proc tuple has changed, it's not valid */
437 2698 : if (!(proc->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
438 1344 : ItemPointerEquals(&proc->fn_tid, &procTup->t_self)))
439 10 : return false;
440 :
441 1344 : return true;
442 : }
443 :
444 : static char *
445 598 : PLy_procedure_munge_source(const char *name, const char *src)
446 : {
447 : char *mrc,
448 : *mp;
449 : const char *sp;
450 : size_t mlen;
451 : int plen;
452 :
453 : /*
454 : * room for function source and the def statement
455 : */
456 598 : mlen = (strlen(src) * 2) + strlen(name) + 16;
457 :
458 598 : mrc = palloc(mlen);
459 598 : plen = snprintf(mrc, mlen, "def %s():\n\t", name);
460 : Assert(plen >= 0 && plen < mlen);
461 :
462 598 : sp = src;
463 598 : mp = mrc + plen;
464 :
465 64362 : while (*sp != '\0')
466 : {
467 63764 : if (*sp == '\r' && *(sp + 1) == '\n')
468 6 : sp++;
469 :
470 63764 : if (*sp == '\n' || *sp == '\r')
471 : {
472 2692 : *mp++ = '\n';
473 2692 : *mp++ = '\t';
474 2692 : sp++;
475 : }
476 : else
477 61072 : *mp++ = *sp++;
478 : }
479 598 : *mp++ = '\n';
480 598 : *mp++ = '\n';
481 598 : *mp = '\0';
482 :
483 598 : if (mp > (mrc + mlen))
484 0 : elog(FATAL, "buffer overrun in PLy_procedure_munge_source");
485 :
486 598 : return mrc;
487 : }
|