2 * Python procedure manipulation for plpython
4 * src/pl/plpython/plpy_procedure.c
41 * PLy_procedure_name: get the name of the specified procedure.
43 * NB: this returns the SQL name, not the internal Python procedure name
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.
82 elog(
ERROR,
"cache lookup failed for function %u", fn_oid);
85 * Look for the function in the cache, unless we don't have the necessary
86 * information (e.g. during validation). In that case we just don't cache
101 /* Haven't found it, create a new procedure */
108 /* Found it, but it's invalid, free and reuse the cache entry */
115 /* Found it and it's valid, it's fine to use it */
119 /* Do not leave an uninitialized entry in the cache */
132 * Create a new PLyProcedure structure
146 rv =
snprintf(procName,
sizeof(procName),
147 "__plpython_procedure_%s_%u",
150 if (rv >=
sizeof(procName) || rv < 0)
151 elog(
ERROR,
"procedure name would overrun buffer");
153 /* Replace any not-legal-in-Python-names characters with '_' */
154 for (ptr = procName; *ptr; ptr++)
156 if (!((*ptr >=
'A' && *ptr <=
'Z') ||
157 (*ptr >=
'a' && *ptr <=
'z') ||
158 (*ptr >=
'0' && *ptr <=
'9')))
162 /* Create long-lived context that all procedure info will live in */
164 "PL/Python function",
174 Datum protrftypes_datum;
185 proc->
fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
186 proc->
is_setof = procStruct->proretset;
187 proc->
is_procedure = (procStruct->prokind == PROKIND_PROCEDURE);
193 proc->
langid = procStruct->prolang;
195 Anum_pg_proc_protrftypes,
205 * get information required for output conversion of the return value,
206 * but only if this isn't a trigger.
210 Oid rettype = procStruct->prorettype;
216 elog(
ERROR,
"cache lookup failed for type %u", rettype);
219 /* Disallow pseudotype result, except for void or record */
220 if (rvTypeStruct->typtype == TYPTYPE_PSEUDO)
222 if (rettype == VOIDOID ||
223 rettype == RECORDOID)
225 else if (rettype == TRIGGEROID || rettype == EVENT_TRIGGEROID)
227 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
228 errmsg(
"trigger functions can only be called as triggers")));
231 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
232 errmsg(
"PL/Python functions cannot return type %s",
236 /* set up output function for procedure result */
245 * In a trigger function, we use proc->result and proc->result_in
246 * for converting tuples, but we don't yet have enough info to set
247 * them up. PLy_exec_trigger will deal with it.
254 * Now get information required for input conversion of the
255 * procedure's arguments. Note that we ignore output arguments here.
256 * If the function returns record, those I/O functions will be set up
257 * when the function is first called.
259 if (procStruct->pronargs)
267 /* extract argument type info from the pg_proc tuple */
270 /* count number of in+inout args into proc->nargs */
275 /* proc->nargs was initialized to 0 above */
276 for (
i = 0;
i < total;
i++)
278 if (modes[
i] != PROARGMODE_OUT &&
279 modes[
i] != PROARGMODE_TABLE)
284 /* Allocate arrays for per-input-argument data */
288 for (
i = pos = 0;
i < total;
i++)
294 (modes[
i] == PROARGMODE_OUT ||
295 modes[
i] == PROARGMODE_TABLE))
296 continue;
/* skip OUT arguments */
298 Assert(
types[
i] == procStruct->proargtypes.values[pos]);
306 /* disallow pseudotype arguments */
307 if (argTypeStruct->typtype == TYPTYPE_PSEUDO)
309 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
310 errmsg(
"PL/Python functions cannot accept type %s",
313 /* set up I/O function info */
315 types[
i], -1,
/* typmod not known */
318 /* get argument name */
328 * get the text of the function.
331 Anum_pg_proc_prosrc);
351 * Insert the procedure into the Python interpreter
356 PyObject *crv = NULL;
363 * SD is private preserved data between calls. GD is global data shared by
372 * insert the function code into the interpreter
375 /* Save the mangled source for later inclusion in tracebacks */
377 code0 = Py_CompileString(msrc,
"<string>", Py_file_input);
379 crv = PyEval_EvalCode(code0, proc->
globals, NULL);
390 * compile a call to the function
393 if (clen < 0 || clen >=
sizeof(call))
394 elog(
ERROR,
"string would overflow buffer");
395 proc->
code = Py_CompileString(call,
"<string>", Py_eval_input);
396 if (proc->
code != NULL)
401 PLy_elog(
ERROR,
"could not compile PL/Python function \"%s\"",
404 PLy_elog(
ERROR,
"could not compile anonymous PL/Python code block");
410 Py_XDECREF(proc->
code);
417 * Decide whether a cached PLyProcedure struct is still valid
425 /* If the pg_proc tuple has changed, it's not valid */
443 * room for function source and the def statement
445 mlen = (strlen(src) * 2) + strlen(
name) + 16;
449 Assert(plen >= 0 && plen < mlen);
456 if (*sp ==
'\r' && *(sp + 1) ==
'\n')
459 if (*sp ==
'\n' || *sp ==
'\r')
472 if (mp > (mrc + mlen))
473 elog(
FATAL,
"buffer overrun in PLy_procedure_munge_source");
#define TextDatumGetCString(d)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
int get_func_arg_info(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
static TransactionId HeapTupleHeaderGetRawXmin(const HeapTupleHeaderData *tup)
static void * GETSTRUCT(const HeapTupleData *tuple)
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
char * MemoryContextStrdup(MemoryContext context, const char *string)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
void MemoryContextDelete(MemoryContext context)
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
List * oid_array_to_list(Datum datum)
FormData_pg_proc * Form_pg_proc
FormData_pg_type * Form_pg_type
PyObject * PLy_interp_globals
char * PLy_procedure_name(PLyProcedure *proc)
void init_procedure_caches(void)
static char * PLy_procedure_munge_source(const char *name, const char *src)
static PLyProcedure * PLy_procedure_create(HeapTuple procTup, Oid fn_oid, PLyTrigType is_trigger)
PLyProcedure * PLy_procedure_get(Oid fn_oid, Oid fn_rel, PLyTrigType is_trigger)
static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup)
static HTAB * PLy_procedure_cache
void PLy_procedure_compile(PLyProcedure *proc, const char *src)
void PLy_procedure_delete(PLyProcedure *proc)
struct PLyProcedureKey PLyProcedureKey
struct PLyProcedureEntry PLyProcedureEntry
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
static Datum ObjectIdGetDatum(Oid X)
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)