#include "access/htup.h"#include "access/tupdesc.h"#include "fmgr.h"#include "storage/itemptr.h"

Go to the source code of this file.
| 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 |
| typedef union PLyTypeOutput PLyTypeOutput |
| 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 | ) |
Definition at line 64 of file plpy_typeio.c.
References PLyObToTuple::atts, PLyTupleToOb::atts, PLyTypeInfo::in, PLyTypeInfo::is_rowtype, ItemPointerSetInvalid, PLyObToTuple::natts, PLyTupleToOb::natts, PLyTypeInfo::out, PLyTypeOutput::r, PLyTypeInput::r, PLyTypeInfo::typ_relid, PLyTypeInfo::typrel_tid, and PLyTypeInfo::typrel_xmin.
Referenced by PLy_cursor_plan(), PLy_cursor_query(), PLy_procedure_create(), PLy_spi_execute_fetch_result(), PLy_spi_prepare(), and PLyObject_ToComposite().
{
arg->is_rowtype = -1;
arg->in.r.natts = arg->out.r.natts = 0;
arg->in.r.atts = NULL;
arg->out.r.atts = NULL;
arg->typ_relid = InvalidOid;
arg->typrel_xmin = InvalidTransactionId;
ItemPointerSetInvalid(&arg->typrel_tid);
}
| 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;
}
1.7.1