#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().