2 * Python procedure manipulation for plpython
4 * src/pl/plpython/plpy_procedure.c
9 #include "access/htup_details.h"
10 #include "catalog/pg_proc.h"
11 #include "catalog/pg_type.h"
13 #include "plpy_elog.h"
14 #include "plpy_main.h"
15 #include "plpy_procedure.h"
17 #include "utils/builtins.h"
18 #include "utils/hsearch.h"
19 #include "utils/memutils.h"
20 #include "utils/syscache.h"
22 static HTAB
*PLy_procedure_cache
= NULL
;
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
);
30 init_procedure_caches(void)
34 hash_ctl
.keysize
= sizeof(PLyProcedureKey
);
35 hash_ctl
.entrysize
= sizeof(PLyProcedureEntry
);
36 PLy_procedure_cache
= hash_create("PL/Python procedures", 32, &hash_ctl
,
37 HASH_ELEM
| HASH_BLOBS
);
41 * PLy_procedure_name: get the name of the specified procedure.
43 * NB: this returns the SQL name, not the internal Python procedure name
46 PLy_procedure_name(PLyProcedure
*proc
)
49 return "<unknown procedure>";
54 * PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
55 * returns a new PLyProcedure.
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
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.
66 PLy_procedure_get(Oid fn_oid
, Oid fn_rel
, bool is_trigger
)
68 bool use_cache
= !(is_trigger
&& fn_rel
== InvalidOid
);
71 PLyProcedureEntry
*volatile entry
= NULL
;
72 PLyProcedure
*volatile proc
= NULL
;
75 procTup
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(fn_oid
));
76 if (!HeapTupleIsValid(procTup
))
77 elog(ERROR
, "cache lookup failed for function %u", fn_oid
);
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
88 entry
= hash_search(PLy_procedure_cache
, &key
, HASH_ENTER
, &found
);
96 /* Haven't found it, create a new procedure */
97 proc
= PLy_procedure_create(procTup
, fn_oid
, is_trigger
);
101 else if (!PLy_procedure_valid(proc
, procTup
))
103 /* Found it, but it's invalid, free and reuse the cache entry */
106 PLy_procedure_delete(proc
);
107 proc
= PLy_procedure_create(procTup
, fn_oid
, is_trigger
);
110 /* Found it and it's valid, it's fine to use it */
114 /* Do not leave an uninitialized entry in the cache */
116 hash_search(PLy_procedure_cache
, &key
, HASH_REMOVE
, NULL
);
121 ReleaseSysCache(procTup
);
127 * Create a new PLyProcedure structure
129 static PLyProcedure
*
130 PLy_procedure_create(HeapTuple procTup
, Oid fn_oid
, bool is_trigger
)
132 char procName
[NAMEDATALEN
+ 256];
133 Form_pg_proc procStruct
;
134 PLyProcedure
*volatile proc
;
136 MemoryContext oldcxt
;
140 procStruct
= (Form_pg_proc
) GETSTRUCT(procTup
);
141 rv
= snprintf(procName
, sizeof(procName
),
142 "__plpython_procedure_%s_%u",
143 NameStr(procStruct
->proname
),
145 if (rv
>= sizeof(procName
) || rv
< 0)
146 elog(ERROR
, "procedure name would overrun buffer");
148 /* Replace any not-legal-in-Python-names characters with '_' */
149 for (ptr
= procName
; *ptr
; ptr
++)
151 if (!((*ptr
>= 'A' && *ptr
<= 'Z') ||
152 (*ptr
>= 'a' && *ptr
<= 'z') ||
153 (*ptr
>= '0' && *ptr
<= '9')))
157 /* Create long-lived context that all procedure info will live in */
158 cxt
= AllocSetContextCreate(TopMemoryContext
,
159 "PL/Python function",
160 ALLOCSET_DEFAULT_SIZES
);
162 oldcxt
= MemoryContextSwitchTo(cxt
);
164 proc
= (PLyProcedure
*) palloc0(sizeof(PLyProcedure
));
169 Datum protrftypes_datum
;
175 proc
->proname
= pstrdup(NameStr(procStruct
->proname
));
176 MemoryContextSetIdentifier(cxt
, proc
->proname
);
177 proc
->pyname
= pstrdup(procName
);
178 proc
->fn_xmin
= HeapTupleHeaderGetRawXmin(procTup
->t_data
);
179 proc
->fn_tid
= procTup
->t_self
;
180 proc
->fn_readonly
= (procStruct
->provolatile
!= PROVOLATILE_VOLATILE
);
181 proc
->is_setof
= procStruct
->proretset
;
182 proc
->is_procedure
= (procStruct
->prokind
== PROKIND_PROCEDURE
);
183 proc
->is_trigger
= is_trigger
;
185 proc
->argnames
= NULL
;
188 proc
->langid
= procStruct
->prolang
;
189 protrftypes_datum
= SysCacheGetAttr(PROCOID
, procTup
,
190 Anum_pg_proc_protrftypes
,
192 proc
->trftypes
= isnull
? NIL
: oid_array_to_list(protrftypes_datum
);
194 proc
->statics
= NULL
;
195 proc
->globals
= NULL
;
197 proc
->argstack
= NULL
;
200 * get information required for output conversion of the return value,
201 * but only if this isn't a trigger.
205 Oid rettype
= procStruct
->prorettype
;
207 Form_pg_type rvTypeStruct
;
209 rvTypeTup
= SearchSysCache1(TYPEOID
, ObjectIdGetDatum(rettype
));
210 if (!HeapTupleIsValid(rvTypeTup
))
211 elog(ERROR
, "cache lookup failed for type %u", rettype
);
212 rvTypeStruct
= (Form_pg_type
) GETSTRUCT(rvTypeTup
);
214 /* Disallow pseudotype result, except for void or record */
215 if (rvTypeStruct
->typtype
== TYPTYPE_PSEUDO
)
217 if (rettype
== VOIDOID
||
218 rettype
== RECORDOID
)
220 else if (rettype
== TRIGGEROID
|| rettype
== EVENT_TRIGGEROID
)
222 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
223 errmsg("trigger functions can only be called as triggers")));
226 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
227 errmsg("PL/Python functions cannot return type %s",
228 format_type_be(rettype
))));
231 /* set up output function for procedure result */
232 PLy_output_setup_func(&proc
->result
, proc
->mcxt
,
235 ReleaseSysCache(rvTypeTup
);
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.
244 proc
->result
.typoid
= InvalidOid
;
245 proc
->result_in
.typoid
= InvalidOid
;
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.
254 if (procStruct
->pronargs
)
262 /* extract argument type info from the pg_proc tuple */
263 total
= get_func_arg_info(procTup
, &types
, &names
, &modes
);
265 /* count number of in+inout args into proc->nargs */
270 /* proc->nargs was initialized to 0 above */
271 for (i
= 0; i
< total
; i
++)
273 if (modes
[i
] != PROARGMODE_OUT
&&
274 modes
[i
] != PROARGMODE_TABLE
)
279 /* Allocate arrays for per-input-argument data */
280 proc
->argnames
= (char **) palloc0(sizeof(char *) * proc
->nargs
);
281 proc
->args
= (PLyDatumToOb
*) palloc0(sizeof(PLyDatumToOb
) * proc
->nargs
);
283 for (i
= pos
= 0; i
< total
; i
++)
285 HeapTuple argTypeTup
;
286 Form_pg_type argTypeStruct
;
289 (modes
[i
] == PROARGMODE_OUT
||
290 modes
[i
] == PROARGMODE_TABLE
))
291 continue; /* skip OUT arguments */
293 Assert(types
[i
] == procStruct
->proargtypes
.values
[pos
]);
295 argTypeTup
= SearchSysCache1(TYPEOID
,
296 ObjectIdGetDatum(types
[i
]));
297 if (!HeapTupleIsValid(argTypeTup
))
298 elog(ERROR
, "cache lookup failed for type %u", types
[i
]);
299 argTypeStruct
= (Form_pg_type
) GETSTRUCT(argTypeTup
);
301 /* disallow pseudotype arguments */
302 if (argTypeStruct
->typtype
== TYPTYPE_PSEUDO
)
304 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
305 errmsg("PL/Python functions cannot accept type %s",
306 format_type_be(types
[i
]))));
308 /* set up I/O function info */
309 PLy_input_setup_func(&proc
->args
[pos
], proc
->mcxt
,
310 types
[i
], -1, /* typmod not known */
313 /* get argument name */
314 proc
->argnames
[pos
] = names
? pstrdup(names
[i
]) : NULL
;
316 ReleaseSysCache(argTypeTup
);
323 * get the text of the function.
325 prosrcdatum
= SysCacheGetAttrNotNull(PROCOID
, procTup
,
326 Anum_pg_proc_prosrc
);
327 procSource
= TextDatumGetCString(prosrcdatum
);
329 PLy_procedure_compile(proc
, procSource
);
335 MemoryContextSwitchTo(oldcxt
);
336 PLy_procedure_delete(proc
);
341 MemoryContextSwitchTo(oldcxt
);
346 * Insert the procedure into the Python interpreter
349 PLy_procedure_compile(PLyProcedure
*proc
, const char *src
)
351 PyObject
*crv
= NULL
;
354 proc
->globals
= PyDict_Copy(PLy_interp_globals
);
357 * SD is private preserved data between calls. GD is global data shared by
360 proc
->statics
= PyDict_New();
362 PLy_elog(ERROR
, NULL
);
363 PyDict_SetItemString(proc
->globals
, "SD", proc
->statics
);
366 * insert the function code into the interpreter
368 msrc
= PLy_procedure_munge_source(proc
->pyname
, src
);
369 /* Save the mangled source for later inclusion in tracebacks */
370 proc
->src
= MemoryContextStrdup(proc
->mcxt
, msrc
);
371 crv
= PyRun_String(msrc
, Py_file_input
, proc
->globals
, NULL
);
377 char call
[NAMEDATALEN
+ 256];
382 * compile a call to the function
384 clen
= snprintf(call
, sizeof(call
), "%s()", proc
->pyname
);
385 if (clen
< 0 || clen
>= sizeof(call
))
386 elog(ERROR
, "string would overflow buffer");
387 proc
->code
= Py_CompileString(call
, "<string>", Py_eval_input
);
388 if (proc
->code
!= NULL
)
393 PLy_elog(ERROR
, "could not compile PL/Python function \"%s\"",
396 PLy_elog(ERROR
, "could not compile anonymous PL/Python code block");
400 PLy_procedure_delete(PLyProcedure
*proc
)
402 Py_XDECREF(proc
->code
);
403 Py_XDECREF(proc
->statics
);
404 Py_XDECREF(proc
->globals
);
405 MemoryContextDelete(proc
->mcxt
);
409 * Decide whether a cached PLyProcedure struct is still valid
412 PLy_procedure_valid(PLyProcedure
*proc
, HeapTuple procTup
)
417 /* If the pg_proc tuple has changed, it's not valid */
418 if (!(proc
->fn_xmin
== HeapTupleHeaderGetRawXmin(procTup
->t_data
) &&
419 ItemPointerEquals(&proc
->fn_tid
, &procTup
->t_self
)))
426 PLy_procedure_munge_source(const char *name
, const char *src
)
435 * room for function source and the def statement
437 mlen
= (strlen(src
) * 2) + strlen(name
) + 16;
440 plen
= snprintf(mrc
, mlen
, "def %s():\n\t", name
);
441 Assert(plen
>= 0 && plen
< mlen
);
448 if (*sp
== '\r' && *(sp
+ 1) == '\n')
451 if (*sp
== '\n' || *sp
== '\r')
464 if (mp
> (mrc
+ mlen
))
465 elog(FATAL
, "buffer overrun in PLy_procedure_munge_source");