Header And Logo

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

Data Structures | Typedefs | Functions

plpy_typeio.h File Reference

#include "access/htup.h"
#include "access/tupdesc.h"
#include "fmgr.h"
#include "storage/itemptr.h"
Include dependency graph for plpy_typeio.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PLyDatumToOb
struct  PLyTupleToOb
union  PLyTypeInput
struct  PLyObToDatum
struct  PLyObToTuple
union  PLyTypeOutput
struct  PLyTypeInfo

Typedefs

typedef PyObject *(* PLyDatumToObFunc )(struct PLyDatumToOb *, Datum)
typedef struct PLyDatumToOb PLyDatumToOb
typedef struct PLyTupleToOb PLyTupleToOb
typedef union PLyTypeInput PLyTypeInput
typedef Datum(* PLyObToDatumFunc )(struct PLyObToDatum *, int32, PyObject *)
typedef struct PLyObToDatum PLyObToDatum
typedef struct PLyObToTuple PLyObToTuple
typedef union PLyTypeOutput PLyTypeOutput
typedef struct PLyTypeInfo PLyTypeInfo

Functions

void PLy_typeinfo_init (PLyTypeInfo *arg)
void PLy_typeinfo_dealloc (PLyTypeInfo *arg)
void PLy_input_datum_func (PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup)
void PLy_output_datum_func (PLyTypeInfo *arg, HeapTuple typeTup)
void PLy_input_tuple_funcs (PLyTypeInfo *arg, TupleDesc desc)
void PLy_output_tuple_funcs (PLyTypeInfo *arg, TupleDesc desc)
void PLy_output_record_funcs (PLyTypeInfo *arg, TupleDesc desc)
Datum PLyObject_ToCompositeDatum (PLyTypeInfo *info, TupleDesc desc, PyObject *plrv)
PyObject * PLyDict_FromTuple (PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)

Typedef Documentation

typedef struct PLyDatumToOb PLyDatumToOb
typedef PyObject*(* PLyDatumToObFunc)(struct PLyDatumToOb *, Datum)

Definition at line 14 of file plpy_typeio.h.

typedef struct PLyObToDatum PLyObToDatum
typedef Datum(* PLyObToDatumFunc)(struct PLyObToDatum *, int32, PyObject *)

Definition at line 45 of file plpy_typeio.h.

typedef struct PLyObToTuple PLyObToTuple
typedef struct PLyTupleToOb PLyTupleToOb
typedef struct PLyTypeInfo PLyTypeInfo
typedef union PLyTypeInput PLyTypeInput

Function Documentation

void PLy_input_datum_func ( PLyTypeInfo arg,
Oid  typeOid,
HeapTuple  typeTup 
)

Definition at line 104 of file plpy_typeio.c.

References PLyTypeInput::d, elog, ERROR, PLyTypeInfo::in, PLyTypeInfo::is_rowtype, and PLy_input_datum_func2().

Referenced by PLy_procedure_create().

{
    if (arg->is_rowtype > 0)
        elog(ERROR, "PLyTypeInfo struct is initialized for Tuple");
    arg->is_rowtype = 0;
    PLy_input_datum_func2(&(arg->in.d), typeOid, typeTup);
}

void PLy_input_tuple_funcs ( PLyTypeInfo arg,
TupleDesc  desc 
)

Definition at line 122 of file plpy_typeio.c.

References Assert, tupleDesc::attrs, PLyTupleToOb::atts, elog, ERROR, HeapTupleHeaderGetXmin, HeapTupleIsValid, i, PLyTypeInfo::in, PLyTypeInfo::is_rowtype, tupleDesc::natts, PLyTupleToOb::natts, ObjectIdGetDatum, OidIsValid, PLy_free(), PLy_input_datum_func2(), PLy_malloc0(), PLyTypeInput::r, RECORDOID, ReleaseSysCache(), RELOID, SearchSysCache1, HeapTupleData::t_data, HeapTupleData::t_self, tupleDesc::tdtypeid, tupleDesc::tdtypmod, PLyTypeInfo::typ_relid, typeidTypeRelid(), TYPEOID, PLyDatumToOb::typoid, PLyTypeInfo::typrel_tid, and PLyTypeInfo::typrel_xmin.

Referenced by PLy_cursor_fetch(), PLy_cursor_iternext(), PLy_exec_trigger(), PLy_function_build_args(), and PLy_spi_execute_fetch_result().

{
    int         i;

    if (arg->is_rowtype == 0)
        elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
    arg->is_rowtype = 1;

    if (arg->in.r.natts != desc->natts)
    {
        if (arg->in.r.atts)
            PLy_free(arg->in.r.atts);
        arg->in.r.natts = desc->natts;
        arg->in.r.atts = PLy_malloc0(desc->natts * sizeof(PLyDatumToOb));
    }

    /* Can this be an unnamed tuple? If not, then an Assert would be enough */
    if (desc->tdtypmod != -1)
        elog(ERROR, "received unnamed record type as input");

    Assert(OidIsValid(desc->tdtypeid));

    /*
     * RECORDOID means we got called to create input functions for a tuple
     * fetched by plpy.execute or for an anonymous record type
     */
    if (desc->tdtypeid != RECORDOID)
    {
        HeapTuple   relTup;

        /* Get the pg_class tuple corresponding to the type of the input */
        arg->typ_relid = typeidTypeRelid(desc->tdtypeid);
        relTup = SearchSysCache1(RELOID, ObjectIdGetDatum(arg->typ_relid));
        if (!HeapTupleIsValid(relTup))
            elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);

        /* Remember XMIN and TID for later validation if cache is still OK */
        arg->typrel_xmin = HeapTupleHeaderGetXmin(relTup->t_data);
        arg->typrel_tid = relTup->t_self;

        ReleaseSysCache(relTup);
    }

    for (i = 0; i < desc->natts; i++)
    {
        HeapTuple   typeTup;

        if (desc->attrs[i]->attisdropped)
            continue;

        if (arg->in.r.atts[i].typoid == desc->attrs[i]->atttypid)
            continue;           /* already set up this entry */

        typeTup = SearchSysCache1(TYPEOID,
                                  ObjectIdGetDatum(desc->attrs[i]->atttypid));
        if (!HeapTupleIsValid(typeTup))
            elog(ERROR, "cache lookup failed for type %u",
                 desc->attrs[i]->atttypid);

        PLy_input_datum_func2(&(arg->in.r.atts[i]),
                              desc->attrs[i]->atttypid,
                              typeTup);

        ReleaseSysCache(typeTup);
    }
}

void PLy_output_datum_func ( PLyTypeInfo arg,
HeapTuple  typeTup 
)

Definition at line 113 of file plpy_typeio.c.

References PLyTypeOutput::d, elog, ERROR, PLyTypeInfo::is_rowtype, PLyTypeInfo::out, and PLy_output_datum_func2().

Referenced by PLy_procedure_create(), and PLy_spi_prepare().

{
    if (arg->is_rowtype > 0)
        elog(ERROR, "PLyTypeInfo struct is initialized for a Tuple");
    arg->is_rowtype = 0;
    PLy_output_datum_func2(&(arg->out.d), typeTup);
}

void PLy_output_record_funcs ( PLyTypeInfo arg,
TupleDesc  desc 
)

Definition at line 252 of file plpy_typeio.c.

References Assert, BlessTupleDesc(), PLyTypeOutput::d, PLyTypeInfo::is_rowtype, PLyTypeInfo::out, PLy_output_tuple_funcs(), tupleDesc::tdtypmod, and PLyObToDatum::typmod.

Referenced by PLy_function_build_args().

{
    /*
     * If the output record functions are already set, we just have to check
     * if the record descriptor has not changed
     */
    if ((arg->is_rowtype == 1) &&
        (arg->out.d.typmod != -1) &&
        (arg->out.d.typmod == desc->tdtypmod))
        return;

    /* bless the record to make it known to the typcache lookup code */
    BlessTupleDesc(desc);
    /* save the freshly generated typmod */
    arg->out.d.typmod = desc->tdtypmod;
    /* proceed with normal I/O function caching */
    PLy_output_tuple_funcs(arg, desc);

    /*
     * it should change is_rowtype to 1, so we won't go through this again
     * unless the output record description changes
     */
    Assert(arg->is_rowtype == 1);
}

void PLy_output_tuple_funcs ( PLyTypeInfo arg,
TupleDesc  desc 
)

Definition at line 190 of file plpy_typeio.c.

References Assert, tupleDesc::attrs, PLyObToTuple::atts, elog, ERROR, HeapTupleHeaderGetXmin, HeapTupleIsValid, i, PLyTypeInfo::is_rowtype, tupleDesc::natts, PLyObToTuple::natts, ObjectIdGetDatum, OidIsValid, PLyTypeInfo::out, PLy_free(), PLy_malloc0(), PLy_output_datum_func2(), PLyTypeOutput::r, RECORDOID, ReleaseSysCache(), RELOID, SearchSysCache1, HeapTupleData::t_data, HeapTupleData::t_self, tupleDesc::tdtypeid, PLyTypeInfo::typ_relid, typeidTypeRelid(), TYPEOID, PLyObToDatum::typoid, PLyTypeInfo::typrel_tid, and PLyTypeInfo::typrel_xmin.

Referenced by PLy_exec_trigger(), PLy_output_record_funcs(), PLyGenericObject_ToComposite(), PLyMapping_ToComposite(), and PLySequence_ToComposite().

{
    int         i;

    if (arg->is_rowtype == 0)
        elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
    arg->is_rowtype = 1;

    if (arg->out.r.natts != desc->natts)
    {
        if (arg->out.r.atts)
            PLy_free(arg->out.r.atts);
        arg->out.r.natts = desc->natts;
        arg->out.r.atts = PLy_malloc0(desc->natts * sizeof(PLyDatumToOb));
    }

    Assert(OidIsValid(desc->tdtypeid));

    /*
     * RECORDOID means we got called to create output functions for an
     * anonymous record type
     */
    if (desc->tdtypeid != RECORDOID)
    {
        HeapTuple   relTup;

        /* Get the pg_class tuple corresponding to the type of the output */
        arg->typ_relid = typeidTypeRelid(desc->tdtypeid);
        relTup = SearchSysCache1(RELOID, ObjectIdGetDatum(arg->typ_relid));
        if (!HeapTupleIsValid(relTup))
            elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);

        /* Remember XMIN and TID for later validation if cache is still OK */
        arg->typrel_xmin = HeapTupleHeaderGetXmin(relTup->t_data);
        arg->typrel_tid = relTup->t_self;

        ReleaseSysCache(relTup);
    }

    for (i = 0; i < desc->natts; i++)
    {
        HeapTuple   typeTup;

        if (desc->attrs[i]->attisdropped)
            continue;

        if (arg->out.r.atts[i].typoid == desc->attrs[i]->atttypid)
            continue;           /* already set up this entry */

        typeTup = SearchSysCache1(TYPEOID,
                                  ObjectIdGetDatum(desc->attrs[i]->atttypid));
        if (!HeapTupleIsValid(typeTup))
            elog(ERROR, "cache lookup failed for type %u",
                 desc->attrs[i]->atttypid);

        PLy_output_datum_func2(&(arg->out.r.atts[i]), typeTup);

        ReleaseSysCache(typeTup);
    }
}

void PLy_typeinfo_dealloc ( PLyTypeInfo arg  ) 

Definition at line 76 of file plpy_typeio.c.

References PLyObToTuple::atts, PLyTupleToOb::atts, PLyObToDatum::elm, PLyDatumToOb::elm, i, PLyTypeInfo::in, PLyTypeInfo::is_rowtype, PLyObToTuple::natts, PLyTupleToOb::natts, NULL, PLyTypeInfo::out, PLy_free(), PLyTypeOutput::r, and PLyTypeInput::r.

Referenced by PLy_cursor_dealloc(), PLy_plan_dealloc(), PLy_spi_execute_fetch_result(), and PLyObject_ToComposite().

{
    if (arg->is_rowtype == 1)
    {
        int         i;

        for (i = 0; i < arg->in.r.natts; i++)
        {
            if (arg->in.r.atts[i].elm != NULL)
                PLy_free(arg->in.r.atts[i].elm);
        }
        if (arg->in.r.atts)
            PLy_free(arg->in.r.atts);
        for (i = 0; i < arg->out.r.natts; i++)
        {
            if (arg->out.r.atts[i].elm != NULL)
                PLy_free(arg->out.r.atts[i].elm);
        }
        if (arg->out.r.atts)
            PLy_free(arg->out.r.atts);
    }
}

void PLy_typeinfo_init ( PLyTypeInfo arg  ) 
PyObject* PLyDict_FromTuple ( PLyTypeInfo info,
HeapTuple  tuple,
TupleDesc  desc 
)

Definition at line 281 of file plpy_typeio.c.

References tupleDesc::attrs, PLyTupleToOb::atts, CurrentMemoryContext, elog, ERROR, PLyDatumToOb::func, heap_getattr, i, PLyTypeInfo::in, PLyTypeInfo::is_rowtype, MemoryContextReset(), MemoryContextSwitchTo(), NameStr, PLyTupleToOb::natts, NULL, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_current_execution_context(), PLy_elog(), PLyTypeInput::r, PLyExecutionContext::scratch_ctx, and value.

Referenced by PLy_cursor_fetch(), PLy_cursor_iternext(), PLy_function_build_args(), PLy_spi_execute_fetch_result(), and PLy_trigger_build_args().

{
    PyObject   *volatile dict;
    PLyExecutionContext *exec_ctx = PLy_current_execution_context();
    MemoryContext oldcontext = CurrentMemoryContext;
    int         i;

    if (info->is_rowtype != 1)
        elog(ERROR, "PLyTypeInfo structure describes a datum");

    dict = PyDict_New();
    if (dict == NULL)
        PLy_elog(ERROR, "could not create new dictionary");

    PG_TRY();
    {
        /*
         * Do the work in the scratch context to avoid leaking memory from the
         * datatype output function calls.
         */
        MemoryContextSwitchTo(exec_ctx->scratch_ctx);
        for (i = 0; i < info->in.r.natts; i++)
        {
            char       *key;
            Datum       vattr;
            bool        is_null;
            PyObject   *value;

            if (desc->attrs[i]->attisdropped)
                continue;

            key = NameStr(desc->attrs[i]->attname);
            vattr = heap_getattr(tuple, (i + 1), desc, &is_null);

            if (is_null || info->in.r.atts[i].func == NULL)
                PyDict_SetItemString(dict, key, Py_None);
            else
            {
                value = (info->in.r.atts[i].func) (&info->in.r.atts[i], vattr);
                PyDict_SetItemString(dict, key, value);
                Py_DECREF(value);
            }
        }
        MemoryContextSwitchTo(oldcontext);
        MemoryContextReset(exec_ctx->scratch_ctx);
    }
    PG_CATCH();
    {
        MemoryContextSwitchTo(oldcontext);
        Py_DECREF(dict);
        PG_RE_THROW();
    }
    PG_END_TRY();

    return dict;
}

Datum PLyObject_ToCompositeDatum ( PLyTypeInfo info,
TupleDesc  desc,
PyObject *  plrv 
)

Definition at line 344 of file plpy_typeio.c.

References PLyGenericObject_ToComposite(), PLyMapping_ToComposite(), PLySequence_ToComposite(), and PLyString_ToComposite().

Referenced by PLy_exec_function(), and PLyObject_ToComposite().

{
    Datum       datum;

    if (PyString_Check(plrv) || PyUnicode_Check(plrv))
        datum = PLyString_ToComposite(info, desc, plrv);
    else if (PySequence_Check(plrv))
        /* composite type as sequence (tuple, list etc) */
        datum = PLySequence_ToComposite(info, desc, plrv);
    else if (PyMapping_Check(plrv))
        /* composite type as mapping (currently only dict) */
        datum = PLyMapping_ToComposite(info, desc, plrv);
    else
        /* returned as smth, must provide method __getattr__(name) */
        datum = PLyGenericObject_ToComposite(info, desc, plrv);

    return datum;
}