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