#include "plpy_typeio.h"

Go to the source code of this file.
Data Structures | |
| struct | PLyProcedure |
| struct | PLyProcedureKey |
| struct | PLyProcedureEntry |
Typedefs | |
| typedef struct PLyProcedure | PLyProcedure |
| typedef struct PLyProcedureKey | PLyProcedureKey |
| typedef struct PLyProcedureEntry | PLyProcedureEntry |
Functions | |
| void | init_procedure_caches (void) |
| char * | PLy_procedure_name (PLyProcedure *proc) |
| PLyProcedure * | PLy_procedure_get (Oid fn_oid, Oid fn_rel, bool is_trigger) |
| void | PLy_procedure_compile (PLyProcedure *proc, const char *src) |
| void | PLy_procedure_delete (PLyProcedure *proc) |
| typedef struct PLyProcedure PLyProcedure |
| typedef struct PLyProcedureEntry PLyProcedureEntry |
| typedef struct PLyProcedureKey PLyProcedureKey |
| void init_procedure_caches | ( | void | ) |
Definition at line 35 of file plpy_procedure.c.
References HASHCTL::entrysize, HASHCTL::hash, hash_create(), HASH_ELEM, HASH_FUNCTION, and HASHCTL::keysize.
Referenced by _PG_init().
{
HASHCTL hash_ctl;
memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(PLyProcedureKey);
hash_ctl.entrysize = sizeof(PLyProcedureEntry);
hash_ctl.hash = tag_hash;
PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
HASH_ELEM | HASH_FUNCTION);
}
| void PLy_procedure_compile | ( | PLyProcedure * | proc, | |
| const char * | src | |||
| ) |
Definition at line 341 of file plpy_procedure.c.
References PLyProcedure::code, elog, ERROR, PLyProcedure::globals, NAMEDATALEN, NULL, pfree(), PLy_elog(), PLy_interp_globals, PLy_procedure_munge_source(), PLy_strdup(), PLyProcedure::proname, PLyProcedure::pyname, snprintf(), PLyProcedure::src, and PLyProcedure::statics.
Referenced by plpython_inline_handler(), and PLy_procedure_create().
{
PyObject *crv = NULL;
char *msrc;
proc->globals = PyDict_Copy(PLy_interp_globals);
/*
* SD is private preserved data between calls. GD is global data shared by
* all functions
*/
proc->statics = PyDict_New();
PyDict_SetItemString(proc->globals, "SD", proc->statics);
/*
* insert the function code into the interpreter
*/
msrc = PLy_procedure_munge_source(proc->pyname, src);
/* Save the mangled source for later inclusion in tracebacks */
proc->src = PLy_strdup(msrc);
crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
pfree(msrc);
if (crv != NULL)
{
int clen;
char call[NAMEDATALEN + 256];
Py_DECREF(crv);
/*
* compile a call to the function
*/
clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
if (clen < 0 || clen >= sizeof(call))
elog(ERROR, "string would overflow buffer");
proc->code = Py_CompileString(call, "<string>", Py_eval_input);
if (proc->code != NULL)
return;
}
if (proc->proname)
PLy_elog(ERROR, "could not compile PL/Python function \"%s\"",
proc->proname);
else
PLy_elog(ERROR, "could not compile anonymous PL/Python code block");
}
| void PLy_procedure_delete | ( | PLyProcedure * | proc | ) |
Definition at line 390 of file plpy_procedure.c.
References PLyProcedure::argnames, PLyProcedure::args, PLyObToTuple::atts, PLyTupleToOb::atts, PLyProcedure::code, PLyProcedure::globals, i, PLyTypeInfo::in, PLyTypeInfo::is_rowtype, PLyProcedure::nargs, PLyTypeInfo::out, PLy_free(), PLyProcedure::proname, PLyProcedure::pyname, PLyTypeOutput::r, PLyTypeInput::r, PLyProcedure::src, and PLyProcedure::statics.
Referenced by plpython_inline_handler(), PLy_procedure_create(), and PLy_procedure_get().
{
int i;
Py_XDECREF(proc->code);
Py_XDECREF(proc->statics);
Py_XDECREF(proc->globals);
if (proc->proname)
PLy_free(proc->proname);
if (proc->pyname)
PLy_free(proc->pyname);
for (i = 0; i < proc->nargs; i++)
{
if (proc->args[i].is_rowtype == 1)
{
if (proc->args[i].in.r.atts)
PLy_free(proc->args[i].in.r.atts);
if (proc->args[i].out.r.atts)
PLy_free(proc->args[i].out.r.atts);
}
if (proc->argnames && proc->argnames[i])
PLy_free(proc->argnames[i]);
}
if (proc->src)
PLy_free(proc->src);
if (proc->argnames)
PLy_free(proc->argnames);
}
| PLyProcedure* PLy_procedure_get | ( | Oid | fn_oid, | |
| Oid | fn_rel, | |||
| bool | is_trigger | |||
| ) |
Definition at line 75 of file plpy_procedure.c.
References elog, ERROR, PLyProcedureKey::fn_oid, PLyProcedureKey::fn_rel, HASH_ENTER, HASH_REMOVE, hash_search(), HeapTupleIsValid, NULL, ObjectIdGetDatum, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_free(), PLy_procedure_create(), PLy_procedure_delete(), PLy_procedure_valid(), PLyProcedureEntry::proc, PROCOID, ReleaseSysCache(), and SearchSysCache1.
Referenced by plpython_call_handler(), and plpython_validator().
{
bool use_cache = !(is_trigger && fn_rel == InvalidOid);
HeapTuple procTup;
PLyProcedureKey key;
PLyProcedureEntry *volatile entry = NULL;
PLyProcedure *volatile proc = NULL;
bool found = false;
procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid));
if (!HeapTupleIsValid(procTup))
elog(ERROR, "cache lookup failed for function %u", fn_oid);
/*
* Look for the function in the cache, unless we don't have the necessary
* information (e.g. during validation). In that case we just don't cache
* anything.
*/
if (use_cache)
{
key.fn_oid = fn_oid;
key.fn_rel = fn_rel;
entry = hash_search(PLy_procedure_cache, &key, HASH_ENTER, &found);
proc = entry->proc;
}
PG_TRY();
{
if (!found)
{
/* Haven't found it, create a new procedure */
proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
if (use_cache)
entry->proc = proc;
}
else if (!PLy_procedure_valid(proc, procTup))
{
/* Found it, but it's invalid, free and reuse the cache entry */
PLy_procedure_delete(proc);
PLy_free(proc);
proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
entry->proc = proc;
}
/* Found it and it's valid, it's fine to use it */
}
PG_CATCH();
{
/* Do not leave an uninitialised entry in the cache */
if (use_cache)
hash_search(PLy_procedure_cache, &key, HASH_REMOVE, NULL);
PG_RE_THROW();
}
PG_END_TRY();
ReleaseSysCache(procTup);
return proc;
}
| char* PLy_procedure_name | ( | PLyProcedure * | proc | ) |
Definition at line 55 of file plpy_procedure.c.
References NULL, and PLyProcedure::proname.
Referenced by plpython_error_callback(), and PLy_traceback().
1.7.1