#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; }