Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Typedefs | Functions

plpy_procedure.h File Reference

#include "plpy_typeio.h"
Include dependency graph for plpy_procedure.h:
This graph shows which files directly or indirectly include this file:

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)
PLyProcedurePLy_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 Documentation

typedef struct PLyProcedure PLyProcedure

Function Documentation

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

{
    if (proc == NULL)
        return "<unknown procedure>";
    return proc->proname;
}