PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plpy_typeio.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/transam.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "parser/parse_type.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/numeric.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
#include "plpython.h"
#include "plpy_typeio.h"
#include "plpy_elog.h"
#include "plpy_main.h"
Include dependency graph for plpy_typeio.c:

Go to the source code of this file.

Functions

static void PLy_input_datum_func2 (PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
 
static void PLy_output_datum_func2 (PLyObToDatum *arg, MemoryContext arg_mcxt, HeapTuple typeTup, Oid langid, List *trftypes)
 
static PyObject * PLyBool_FromBool (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyFloat_FromFloat4 (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyFloat_FromFloat8 (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyDecimal_FromNumeric (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyInt_FromInt16 (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyInt_FromInt32 (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyLong_FromInt64 (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyLong_FromOid (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyBytes_FromBytea (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyString_FromDatum (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyObject_FromTransform (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyList_FromArray (PLyDatumToOb *arg, Datum d)
 
static PyObject * PLyList_FromArray_recurse (PLyDatumToOb *elm, int *dims, int ndim, int dim, char **dataptr_p, bits8 **bitmap_p, int *bitmask_p)
 
static Datum PLyObject_ToBool (PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
 
static Datum PLyObject_ToBytea (PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
 
static Datum PLyObject_ToComposite (PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
 
static Datum PLyObject_ToDatum (PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
 
static Datum PLyObject_ToTransform (PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
 
static Datum PLySequence_ToArray (PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
 
static void PLySequence_ToArray_recurse (PLyObToDatum *elm, PyObject *list, int *dims, int ndim, int dim, Datum *elems, bool *nulls, int *currelem)
 
static Datum PLyString_ToComposite (PLyTypeInfo *info, TupleDesc desc, PyObject *string, bool inarray)
 
static Datum PLyMapping_ToComposite (PLyTypeInfo *info, TupleDesc desc, PyObject *mapping)
 
static Datum PLySequence_ToComposite (PLyTypeInfo *info, TupleDesc desc, PyObject *sequence)
 
static Datum PLyGenericObject_ToComposite (PLyTypeInfo *info, TupleDesc desc, PyObject *object, bool inarray)
 
void PLy_typeinfo_init (PLyTypeInfo *arg, MemoryContext mcxt)
 
void PLy_input_datum_func (PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
 
void PLy_output_datum_func (PLyTypeInfo *arg, HeapTuple typeTup, Oid langid, List *trftypes)
 
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)
 
PyObject * PLyDict_FromTuple (PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)
 
Datum PLyObject_ToCompositeDatum (PLyTypeInfo *info, TupleDesc desc, PyObject *plrv, bool inarray)
 
char * PLyObject_AsString (PyObject *plrv)
 

Function Documentation

void PLy_input_datum_func ( PLyTypeInfo arg,
Oid  typeOid,
HeapTuple  typeTup,
Oid  langid,
List trftypes 
)

Definition at line 87 of file plpy_typeio.c.

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

Referenced by PLy_procedure_create().

88 {
89  if (arg->is_rowtype > 0)
90  elog(ERROR, "PLyTypeInfo struct is initialized for Tuple");
91  arg->is_rowtype = 0;
92  PLy_input_datum_func2(&(arg->in.d), arg->mcxt, typeOid, typeTup, langid, trftypes);
93 }
static void PLy_input_datum_func2(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:438
PLyTypeInput in
Definition: plpy_typeio.h:86
#define ERROR
Definition: elog.h:43
MemoryContext mcxt
Definition: plpy_typeio.h:100
int is_rowtype
Definition: plpy_typeio.h:93
#define elog
Definition: elog.h:219
PLyDatumToOb d
Definition: plpy_typeio.h:41
static void PLy_input_datum_func2 ( PLyDatumToOb arg,
MemoryContext  arg_mcxt,
Oid  typeOid,
HeapTuple  typeTup,
Oid  langid,
List trftypes 
)
static

Definition at line 438 of file plpy_typeio.c.

References BOOLOID, BYTEAOID, PLyDatumToOb::elm, FLOAT4OID, FLOAT8OID, fmgr_info_cxt(), PLyDatumToOb::func, get_base_element_type(), get_transform_fromsql(), get_type_io_data(), getBaseType(), GETSTRUCT, getTypeIOParam(), HeapTupleGetOid, INT2OID, INT4OID, INT8OID, IOFunc_output, MemoryContextSwitchTo(), NUMERICOID, OIDOID, palloc0(), PLyBool_FromBool(), PLyBytes_FromBytea(), PLyDecimal_FromNumeric(), PLyFloat_FromFloat4(), PLyFloat_FromFloat8(), PLyInt_FromInt16(), PLyInt_FromInt32(), PLyList_FromArray(), PLyLong_FromInt64(), PLyLong_FromOid(), PLyObject_FromTransform(), PLyString_FromDatum(), PLyDatumToOb::typalign, PLyDatumToOb::typbyval, PLyDatumToOb::typfunc, PLyDatumToOb::typioparam, PLyDatumToOb::typlen, PLyDatumToOb::typmod, PLyDatumToOb::typoid, and PLyDatumToOb::typtransform.

Referenced by PLy_input_datum_func(), and PLy_input_tuple_funcs().

439 {
440  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
441  Oid element_type;
442  Oid base_type;
443  Oid funcid;
444  MemoryContext oldcxt;
445 
446  oldcxt = MemoryContextSwitchTo(arg_mcxt);
447 
448  /* Get the type's conversion information */
449  fmgr_info_cxt(typeStruct->typoutput, &arg->typfunc, arg_mcxt);
450  arg->typoid = HeapTupleGetOid(typeTup);
451  arg->typmod = -1;
452  arg->typioparam = getTypeIOParam(typeTup);
453  arg->typbyval = typeStruct->typbyval;
454  arg->typlen = typeStruct->typlen;
455  arg->typalign = typeStruct->typalign;
456 
457  /* Determine which kind of Python object we will convert to */
458 
459  element_type = get_base_element_type(typeOid);
460  base_type = getBaseType(element_type ? element_type : typeOid);
461 
462  if ((funcid = get_transform_fromsql(base_type, langid, trftypes)))
463  {
465  fmgr_info_cxt(funcid, &arg->typtransform, arg_mcxt);
466  }
467  else
468  switch (base_type)
469  {
470  case BOOLOID:
471  arg->func = PLyBool_FromBool;
472  break;
473  case FLOAT4OID:
474  arg->func = PLyFloat_FromFloat4;
475  break;
476  case FLOAT8OID:
477  arg->func = PLyFloat_FromFloat8;
478  break;
479  case NUMERICOID:
481  break;
482  case INT2OID:
483  arg->func = PLyInt_FromInt16;
484  break;
485  case INT4OID:
486  arg->func = PLyInt_FromInt32;
487  break;
488  case INT8OID:
489  arg->func = PLyLong_FromInt64;
490  break;
491  case OIDOID:
492  arg->func = PLyLong_FromOid;
493  break;
494  case BYTEAOID:
495  arg->func = PLyBytes_FromBytea;
496  break;
497  default:
498  arg->func = PLyString_FromDatum;
499  break;
500  }
501 
502  if (element_type)
503  {
504  char dummy_delim;
505  Oid funcid;
506 
507  arg->elm = palloc0(sizeof(*arg->elm));
508  arg->elm->func = arg->func;
509  arg->elm->typtransform = arg->typtransform;
510  arg->func = PLyList_FromArray;
511  arg->elm->typoid = element_type;
512  arg->elm->typmod = -1;
513  get_type_io_data(element_type, IOFunc_output,
514  &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
515  &arg->elm->typioparam, &funcid);
516  fmgr_info_cxt(funcid, &arg->elm->typfunc, arg_mcxt);
517  }
518 
519  MemoryContextSwitchTo(oldcxt);
520 }
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1872
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:589
static PyObject * PLyInt_FromInt32(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:583
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:523
#define OIDOID
Definition: pg_type.h:328
#define NUMERICOID
Definition: pg_type.h:554
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define INT4OID
Definition: pg_type.h:316
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
static PyObject * PLyInt_FromInt16(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:577
static PyObject * PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:537
PLyDatumToObFunc func
Definition: plpy_typeio.h:21
#define INT2OID
Definition: pg_type.h:308
static PyObject * PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:531
static PyObject * PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:605
int32 typmod
Definition: plpy_typeio.h:25
FmgrInfo typfunc
Definition: plpy_typeio.h:22
struct PLyDatumToOb * elm
Definition: plpy_typeio.h:30
int16 typlen
Definition: plpy_typeio.h:28
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
static PyObject * PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:543
#define FLOAT4OID
Definition: pg_type.h:416
void * palloc0(Size size)
Definition: mcxt.c:877
static PyObject * PLyString_FromDatum(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:615
FmgrInfo typtransform
Definition: plpy_typeio.h:23
#define INT8OID
Definition: pg_type.h:304
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:631
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:599
#define FLOAT8OID
Definition: pg_type.h:419
#define BOOLOID
Definition: pg_type.h:288
#define BYTEAOID
Definition: pg_type.h:292
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2557
static PyObject * PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:625
Oid getTypeIOParam(HeapTuple typeTuple)
Definition: lsyscache.c:2053
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2271
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2075
void PLy_input_tuple_funcs ( PLyTypeInfo arg,
TupleDesc  desc 
)

Definition at line 105 of file plpy_typeio.c.

References Assert, PLyTupleToOb::atts, PLyExecutionContext::curr_proc, elog, ERROR, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, i, PLyTypeInfo::in, PLyTypeInfo::is_rowtype, PLyProcedure::langid, PLyTypeInfo::mcxt, MemoryContextSwitchTo(), PLyTupleToOb::natts, tupleDesc::natts, ObjectIdGetDatum, OidIsValid, palloc0(), pfree(), PLy_current_execution_context(), PLy_input_datum_func2(), PLyTypeInput::r, RECORDOID, ReleaseSysCache(), RELOID, SearchSysCache1(), HeapTupleData::t_data, HeapTupleData::t_self, tupleDesc::tdtypeid, tupleDesc::tdtypmod, PLyProcedure::trftypes, TupleDescAttr, 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().

106 {
107  int i;
109  MemoryContext oldcxt;
110 
111  oldcxt = MemoryContextSwitchTo(arg->mcxt);
112 
113  if (arg->is_rowtype == 0)
114  elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
115  arg->is_rowtype = 1;
116 
117  if (arg->in.r.natts != desc->natts)
118  {
119  if (arg->in.r.atts)
120  pfree(arg->in.r.atts);
121  arg->in.r.natts = desc->natts;
122  arg->in.r.atts = palloc0(desc->natts * sizeof(PLyDatumToOb));
123  }
124 
125  /* Can this be an unnamed tuple? If not, then an Assert would be enough */
126  if (desc->tdtypmod != -1)
127  elog(ERROR, "received unnamed record type as input");
128 
129  Assert(OidIsValid(desc->tdtypeid));
130 
131  /*
132  * RECORDOID means we got called to create input functions for a tuple
133  * fetched by plpy.execute or for an anonymous record type
134  */
135  if (desc->tdtypeid != RECORDOID)
136  {
137  HeapTuple relTup;
138 
139  /* Get the pg_class tuple corresponding to the type of the input */
140  arg->typ_relid = typeidTypeRelid(desc->tdtypeid);
142  if (!HeapTupleIsValid(relTup))
143  elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);
144 
145  /* Remember XMIN and TID for later validation if cache is still OK */
147  arg->typrel_tid = relTup->t_self;
148 
149  ReleaseSysCache(relTup);
150  }
151 
152  for (i = 0; i < desc->natts; i++)
153  {
154  HeapTuple typeTup;
155  Form_pg_attribute attr = TupleDescAttr(desc, i);
156 
157  if (attr->attisdropped)
158  continue;
159 
160  if (arg->in.r.atts[i].typoid == attr->atttypid)
161  continue; /* already set up this entry */
162 
163  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(attr->atttypid));
164  if (!HeapTupleIsValid(typeTup))
165  elog(ERROR, "cache lookup failed for type %u",
166  attr->atttypid);
167 
168  PLy_input_datum_func2(&(arg->in.r.atts[i]), arg->mcxt,
169  attr->atttypid,
170  typeTup,
171  exec_ctx->curr_proc->langid,
172  exec_ctx->curr_proc->trftypes);
173 
174  ReleaseSysCache(typeTup);
175  }
176 
177  MemoryContextSwitchTo(oldcxt);
178 }
TransactionId typrel_xmin
Definition: plpy_typeio.h:96
Oid tdtypeid
Definition: tupdesc.h:74
PLyDatumToOb * atts
Definition: plpy_typeio.h:35
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Oid typeidTypeRelid(Oid type_id)
Definition: parse_type.c:646
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:398
#define OidIsValid(objectId)
Definition: c.h:532
int natts
Definition: tupdesc.h:73
int32 tdtypmod
Definition: tupdesc.h:75
HeapTupleHeader t_data
Definition: htup.h:67
ItemPointerData typrel_tid
Definition: plpy_typeio.h:97
void pfree(void *pointer)
Definition: mcxt.c:949
static void PLy_input_datum_func2(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:438
PLyTypeInput in
Definition: plpy_typeio.h:86
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define RECORDOID
Definition: pg_type.h:680
PLyProcedure * curr_proc
Definition: plpy_main.h:20
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void * palloc0(Size size)
Definition: mcxt.c:877
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
PLyTupleToOb r
Definition: plpy_typeio.h:42
MemoryContext mcxt
Definition: plpy_typeio.h:100
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
int is_rowtype
Definition: plpy_typeio.h:93
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
int i
#define elog
Definition: elog.h:219
void PLy_output_datum_func ( PLyTypeInfo arg,
HeapTuple  typeTup,
Oid  langid,
List trftypes 
)

Definition at line 96 of file plpy_typeio.c.

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

Referenced by PLy_procedure_create(), and PLy_spi_prepare().

97 {
98  if (arg->is_rowtype > 0)
99  elog(ERROR, "PLyTypeInfo struct is initialized for a Tuple");
100  arg->is_rowtype = 0;
101  PLy_output_datum_func2(&(arg->out.d), arg->mcxt, typeTup, langid, trftypes);
102 }
#define ERROR
Definition: elog.h:43
PLyObToDatum d
Definition: plpy_typeio.h:77
PLyTypeOutput out
Definition: plpy_typeio.h:87
MemoryContext mcxt
Definition: plpy_typeio.h:100
int is_rowtype
Definition: plpy_typeio.h:93
static void PLy_output_datum_func2(PLyObToDatum *arg, MemoryContext arg_mcxt, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:366
#define elog
Definition: elog.h:219
static void PLy_output_datum_func2 ( PLyObToDatum arg,
MemoryContext  arg_mcxt,
HeapTuple  typeTup,
Oid  langid,
List trftypes 
)
static

Definition at line 366 of file plpy_typeio.c.

References BOOLOID, BYTEAOID, PLyObToDatum::elm, fmgr_info_cxt(), PLyObToDatum::func, get_base_element_type(), get_transform_tosql(), get_type_io_data(), getBaseType(), GETSTRUCT, getTypeIOParam(), HeapTupleGetOid, IOFunc_input, MemoryContextSwitchTo(), palloc0(), PLyObject_ToBool(), PLyObject_ToBytea(), PLyObject_ToComposite(), PLyObject_ToDatum(), PLyObject_ToTransform(), PLySequence_ToArray(), PLyObToDatum::typalign, PLyObToDatum::typbyval, type_is_rowtype(), PLyObToDatum::typfunc, PLyObToDatum::typioparam, PLyObToDatum::typlen, PLyObToDatum::typmod, PLyObToDatum::typoid, PLyObToDatum::typtransform, and TYPTYPE_COMPOSITE.

Referenced by PLy_output_datum_func(), PLy_output_tuple_funcs(), and PLyString_ToComposite().

367 {
368  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
369  Oid element_type;
370  Oid base_type;
371  Oid funcid;
372  MemoryContext oldcxt;
373 
374  oldcxt = MemoryContextSwitchTo(arg_mcxt);
375 
376  fmgr_info_cxt(typeStruct->typinput, &arg->typfunc, arg_mcxt);
377  arg->typoid = HeapTupleGetOid(typeTup);
378  arg->typmod = -1;
379  arg->typioparam = getTypeIOParam(typeTup);
380  arg->typbyval = typeStruct->typbyval;
381 
382  element_type = get_base_element_type(arg->typoid);
383  base_type = getBaseType(element_type ? element_type : arg->typoid);
384 
385  /*
386  * Select a conversion function to convert Python objects to PostgreSQL
387  * datums.
388  */
389 
390  if ((funcid = get_transform_tosql(base_type, langid, trftypes)))
391  {
393  fmgr_info_cxt(funcid, &arg->typtransform, arg_mcxt);
394  }
395  else if (typeStruct->typtype == TYPTYPE_COMPOSITE)
396  {
398  }
399  else
400  switch (base_type)
401  {
402  case BOOLOID:
403  arg->func = PLyObject_ToBool;
404  break;
405  case BYTEAOID:
406  arg->func = PLyObject_ToBytea;
407  break;
408  default:
409  arg->func = PLyObject_ToDatum;
410  break;
411  }
412 
413  if (element_type)
414  {
415  char dummy_delim;
416  Oid funcid;
417 
418  if (type_is_rowtype(element_type))
420 
421  arg->elm = palloc0(sizeof(*arg->elm));
422  arg->elm->func = arg->func;
423  arg->elm->typtransform = arg->typtransform;
424  arg->func = PLySequence_ToArray;
425 
426  arg->elm->typoid = element_type;
427  arg->elm->typmod = -1;
428  get_type_io_data(element_type, IOFunc_input,
429  &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
430  &arg->elm->typioparam, &funcid);
431  fmgr_info_cxt(funcid, &arg->elm->typfunc, arg_mcxt);
432  }
433 
434  MemoryContextSwitchTo(oldcxt);
435 }
FmgrInfo typfunc
Definition: plpy_typeio.h:58
static Datum PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:746
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
PLyObToDatumFunc func
Definition: plpy_typeio.h:57
int32 typmod
Definition: plpy_typeio.h:61
static Datum PLyObject_ToTransform(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:964
static Datum PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:809
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2404
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
void * palloc0(Size size)
Definition: mcxt.c:877
#define BOOLOID
Definition: pg_type.h:288
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1893
#define BYTEAOID
Definition: pg_type.h:292
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2557
static Datum PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:971
struct PLyObToDatum * elm
Definition: plpy_typeio.h:66
Oid getTypeIOParam(HeapTuple typeTuple)
Definition: lsyscache.c:2053
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2271
static Datum PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:908
static Datum PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:765
FmgrInfo typtransform
Definition: plpy_typeio.h:59
int16 typlen
Definition: plpy_typeio.h:64
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2075
void PLy_output_record_funcs ( PLyTypeInfo arg,
TupleDesc  desc 
)

Definition at line 251 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().

252 {
253  /*
254  * If the output record functions are already set, we just have to check
255  * if the record descriptor has not changed
256  */
257  if ((arg->is_rowtype == 1) &&
258  (arg->out.d.typmod != -1) &&
259  (arg->out.d.typmod == desc->tdtypmod))
260  return;
261 
262  /* bless the record to make it known to the typcache lookup code */
263  BlessTupleDesc(desc);
264  /* save the freshly generated typmod */
265  arg->out.d.typmod = desc->tdtypmod;
266  /* proceed with normal I/O function caching */
267  PLy_output_tuple_funcs(arg, desc);
268 
269  /*
270  * it should change is_rowtype to 1, so we won't go through this again
271  * unless the output record description changes
272  */
273  Assert(arg->is_rowtype == 1);
274 }
void PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:181
int32 typmod
Definition: plpy_typeio.h:61
int32 tdtypmod
Definition: tupdesc.h:75
PLyObToDatum d
Definition: plpy_typeio.h:77
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
PLyTypeOutput out
Definition: plpy_typeio.h:87
#define Assert(condition)
Definition: c.h:681
int is_rowtype
Definition: plpy_typeio.h:93
void PLy_output_tuple_funcs ( PLyTypeInfo arg,
TupleDesc  desc 
)

Definition at line 181 of file plpy_typeio.c.

References Assert, PLyObToTuple::atts, PLyExecutionContext::curr_proc, elog, ERROR, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, i, PLyTypeInfo::is_rowtype, PLyProcedure::langid, PLyTypeInfo::mcxt, MemoryContextSwitchTo(), PLyObToTuple::natts, tupleDesc::natts, ObjectIdGetDatum, OidIsValid, PLyTypeInfo::out, palloc0(), pfree(), PLy_current_execution_context(), PLy_output_datum_func2(), PLyTypeOutput::r, RECORDOID, ReleaseSysCache(), RELOID, SearchSysCache1(), HeapTupleData::t_data, HeapTupleData::t_self, tupleDesc::tdtypeid, PLyProcedure::trftypes, TupleDescAttr, 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().

182 {
183  int i;
185  MemoryContext oldcxt;
186 
187  oldcxt = MemoryContextSwitchTo(arg->mcxt);
188 
189  if (arg->is_rowtype == 0)
190  elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
191  arg->is_rowtype = 1;
192 
193  if (arg->out.r.natts != desc->natts)
194  {
195  if (arg->out.r.atts)
196  pfree(arg->out.r.atts);
197  arg->out.r.natts = desc->natts;
198  arg->out.r.atts = palloc0(desc->natts * sizeof(PLyObToDatum));
199  }
200 
201  Assert(OidIsValid(desc->tdtypeid));
202 
203  /*
204  * RECORDOID means we got called to create output functions for an
205  * anonymous record type
206  */
207  if (desc->tdtypeid != RECORDOID)
208  {
209  HeapTuple relTup;
210 
211  /* Get the pg_class tuple corresponding to the type of the output */
212  arg->typ_relid = typeidTypeRelid(desc->tdtypeid);
214  if (!HeapTupleIsValid(relTup))
215  elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);
216 
217  /* Remember XMIN and TID for later validation if cache is still OK */
219  arg->typrel_tid = relTup->t_self;
220 
221  ReleaseSysCache(relTup);
222  }
223 
224  for (i = 0; i < desc->natts; i++)
225  {
226  HeapTuple typeTup;
227  Form_pg_attribute attr = TupleDescAttr(desc, i);
228 
229  if (attr->attisdropped)
230  continue;
231 
232  if (arg->out.r.atts[i].typoid == attr->atttypid)
233  continue; /* already set up this entry */
234 
235  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(attr->atttypid));
236  if (!HeapTupleIsValid(typeTup))
237  elog(ERROR, "cache lookup failed for type %u",
238  attr->atttypid);
239 
240  PLy_output_datum_func2(&(arg->out.r.atts[i]), arg->mcxt, typeTup,
241  exec_ctx->curr_proc->langid,
242  exec_ctx->curr_proc->trftypes);
243 
244  ReleaseSysCache(typeTup);
245  }
246 
247  MemoryContextSwitchTo(oldcxt);
248 }
TransactionId typrel_xmin
Definition: plpy_typeio.h:96
Oid tdtypeid
Definition: tupdesc.h:74
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Oid typeidTypeRelid(Oid type_id)
Definition: parse_type.c:646
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:398
#define OidIsValid(objectId)
Definition: c.h:532
int natts
Definition: tupdesc.h:73
HeapTupleHeader t_data
Definition: htup.h:67
ItemPointerData typrel_tid
Definition: plpy_typeio.h:97
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
PLyTypeOutput out
Definition: plpy_typeio.h:87
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define RECORDOID
Definition: pg_type.h:680
PLyProcedure * curr_proc
Definition: plpy_main.h:20
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void * palloc0(Size size)
Definition: mcxt.c:877
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
MemoryContext mcxt
Definition: plpy_typeio.h:100
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
int is_rowtype
Definition: plpy_typeio.h:93
PLyObToTuple r
Definition: plpy_typeio.h:78
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
static void PLy_output_datum_func2(PLyObToDatum *arg, MemoryContext arg_mcxt, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:366
int i
PLyObToDatum * atts
Definition: plpy_typeio.h:71
#define elog
Definition: elog.h:219
void PLy_typeinfo_init ( PLyTypeInfo arg,
MemoryContext  mcxt 
)

Definition at line 70 of file plpy_typeio.c.

References PLyTupleToOb::atts, PLyObToTuple::atts, PLyTypeInfo::in, InvalidOid, InvalidTransactionId, PLyTypeInfo::is_rowtype, ItemPointerSetInvalid, PLyTypeInfo::mcxt, PLyTupleToOb::natts, PLyObToTuple::natts, PLyTypeInfo::out, PLyTypeInput::r, PLyTypeOutput::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(), PLyObject_ToComposite(), and PLyString_ToComposite().

71 {
72  arg->is_rowtype = -1;
73  arg->in.r.natts = arg->out.r.natts = 0;
74  arg->in.r.atts = NULL;
75  arg->out.r.atts = NULL;
76  arg->typ_relid = InvalidOid;
79  arg->mcxt = mcxt;
80 }
TransactionId typrel_xmin
Definition: plpy_typeio.h:96
PLyDatumToOb * atts
Definition: plpy_typeio.h:35
ItemPointerData typrel_tid
Definition: plpy_typeio.h:97
PLyTypeInput in
Definition: plpy_typeio.h:86
PLyTypeOutput out
Definition: plpy_typeio.h:87
#define InvalidTransactionId
Definition: transam.h:31
PLyTupleToOb r
Definition: plpy_typeio.h:42
#define InvalidOid
Definition: postgres_ext.h:36
MemoryContext mcxt
Definition: plpy_typeio.h:100
int is_rowtype
Definition: plpy_typeio.h:93
PLyObToTuple r
Definition: plpy_typeio.h:78
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
PLyObToDatum * atts
Definition: plpy_typeio.h:71
static PyObject * PLyBool_FromBool ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 523 of file plpy_typeio.c.

References DatumGetBool.

Referenced by PLy_input_datum_func2().

524 {
525  if (DatumGetBool(d))
526  Py_RETURN_TRUE;
527  Py_RETURN_FALSE;
528 }
#define DatumGetBool(X)
Definition: postgres.h:399
static PyObject * PLyBytes_FromBytea ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 605 of file plpy_typeio.c.

References DatumGetByteaPP, PyBytes_FromStringAndSize, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by PLy_input_datum_func2().

606 {
607  text *txt = DatumGetByteaPP(d);
608  char *str = VARDATA_ANY(txt);
609  size_t size = VARSIZE_ANY_EXHDR(txt);
610 
611  return PyBytes_FromStringAndSize(str, size);
612 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
#define PyBytes_FromStringAndSize
Definition: plpython.h:85
#define DatumGetByteaPP(X)
Definition: fmgr.h:255
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
Definition: c.h:433
static PyObject * PLyDecimal_FromNumeric ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 543 of file plpy_typeio.c.

References DatumGetCString, DirectFunctionCall1, ERROR, numeric_out(), and PLy_elog().

Referenced by PLy_input_datum_func2().

544 {
545  static PyObject *decimal_constructor;
546  char *str;
547  PyObject *pyvalue;
548 
549  /* Try to import cdecimal. If it doesn't exist, fall back to decimal. */
550  if (!decimal_constructor)
551  {
552  PyObject *decimal_module;
553 
554  decimal_module = PyImport_ImportModule("cdecimal");
555  if (!decimal_module)
556  {
557  PyErr_Clear();
558  decimal_module = PyImport_ImportModule("decimal");
559  }
560  if (!decimal_module)
561  PLy_elog(ERROR, "could not import a module for Decimal constructor");
562 
563  decimal_constructor = PyObject_GetAttrString(decimal_module, "Decimal");
564  if (!decimal_constructor)
565  PLy_elog(ERROR, "no Decimal attribute in module");
566  }
567 
569  pyvalue = PyObject_CallFunction(decimal_constructor, "s", str);
570  if (!pyvalue)
571  PLy_elog(ERROR, "conversion from numeric to Decimal failed");
572 
573  return pyvalue;
574 }
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:651
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:572
PyObject* PLyDict_FromTuple ( PLyTypeInfo info,
HeapTuple  tuple,
TupleDesc  desc 
)

Definition at line 280 of file plpy_typeio.c.

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

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

281 {
282  PyObject *volatile dict;
284  MemoryContext scratch_context = PLy_get_scratch_context(exec_ctx);
285  MemoryContext oldcontext = CurrentMemoryContext;
286 
287  if (info->is_rowtype != 1)
288  elog(ERROR, "PLyTypeInfo structure describes a datum");
289 
290  dict = PyDict_New();
291  if (dict == NULL)
292  PLy_elog(ERROR, "could not create new dictionary");
293 
294  PG_TRY();
295  {
296  int i;
297 
298  /*
299  * Do the work in the scratch context to avoid leaking memory from the
300  * datatype output function calls.
301  */
302  MemoryContextSwitchTo(scratch_context);
303  for (i = 0; i < info->in.r.natts; i++)
304  {
305  char *key;
306  Datum vattr;
307  bool is_null;
308  PyObject *value;
309  Form_pg_attribute attr = TupleDescAttr(desc, i);
310 
311  if (attr->attisdropped)
312  continue;
313 
314  key = NameStr(attr->attname);
315  vattr = heap_getattr(tuple, (i + 1), desc, &is_null);
316 
317  if (is_null || info->in.r.atts[i].func == NULL)
318  PyDict_SetItemString(dict, key, Py_None);
319  else
320  {
321  value = (info->in.r.atts[i].func) (&info->in.r.atts[i], vattr);
322  PyDict_SetItemString(dict, key, value);
323  Py_DECREF(value);
324  }
325  }
326  MemoryContextSwitchTo(oldcontext);
327  MemoryContextReset(scratch_context);
328  }
329  PG_CATCH();
330  {
331  MemoryContextSwitchTo(oldcontext);
332  Py_DECREF(dict);
333  PG_RE_THROW();
334  }
335  PG_END_TRY();
336 
337  return dict;
338 }
PLyDatumToOb * atts
Definition: plpy_typeio.h:35
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:398
PLyTypeInput in
Definition: plpy_typeio.h:86
#define ERROR
Definition: elog.h:43
PLyDatumToObFunc func
Definition: plpy_typeio.h:21
static struct @121 value
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
uintptr_t Datum
Definition: postgres.h:372
PLyTupleToOb r
Definition: plpy_typeio.h:42
#define PG_CATCH()
Definition: elog.h:293
int is_rowtype
Definition: plpy_typeio.h:93
#define PG_RE_THROW()
Definition: elog.h:314
int i
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
Definition: plpy_main.c:407
static PyObject * PLyFloat_FromFloat4 ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 531 of file plpy_typeio.c.

References DatumGetFloat4.

Referenced by PLy_input_datum_func2().

532 {
533  return PyFloat_FromDouble(DatumGetFloat4(d));
534 }
#define DatumGetFloat4(X)
Definition: postgres.h:686
static PyObject * PLyFloat_FromFloat8 ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 537 of file plpy_typeio.c.

References DatumGetFloat8.

Referenced by PLy_input_datum_func2().

538 {
539  return PyFloat_FromDouble(DatumGetFloat8(d));
540 }
#define DatumGetFloat8(X)
Definition: postgres.h:734
static Datum PLyGenericObject_ToComposite ( PLyTypeInfo info,
TupleDesc  desc,
PyObject *  object,
bool  inarray 
)
static

Definition at line 1331 of file plpy_typeio.c.

References Assert, PLyObToTuple::atts, ereport, errcode(), errhint(), errmsg(), ERROR, PLyObToDatum::func, heap_copy_tuple_as_datum(), heap_form_tuple(), heap_freetuple(), i, PLyTypeInfo::is_rowtype, NameStr, tupleDesc::natts, PLyTypeInfo::out, palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_output_tuple_funcs(), PLyTypeOutput::r, TupleDescAttr, value, and values.

Referenced by PLyObject_ToCompositeDatum().

1332 {
1333  Datum result;
1334  HeapTuple tuple;
1335  Datum *values;
1336  bool *nulls;
1337  volatile int i;
1338 
1339  if (info->is_rowtype == 2)
1340  PLy_output_tuple_funcs(info, desc);
1341  Assert(info->is_rowtype == 1);
1342 
1343  /* Build tuple */
1344  values = palloc(sizeof(Datum) * desc->natts);
1345  nulls = palloc(sizeof(bool) * desc->natts);
1346  for (i = 0; i < desc->natts; ++i)
1347  {
1348  char *key;
1349  PyObject *volatile value;
1350  PLyObToDatum *att;
1351  Form_pg_attribute attr = TupleDescAttr(desc, i);
1352 
1353  if (attr->attisdropped)
1354  {
1355  values[i] = (Datum) 0;
1356  nulls[i] = true;
1357  continue;
1358  }
1359 
1360  key = NameStr(attr->attname);
1361  value = NULL;
1362  att = &info->out.r.atts[i];
1363  PG_TRY();
1364  {
1365  value = PyObject_GetAttrString(object, key);
1366  if (value == Py_None)
1367  {
1368  values[i] = (Datum) NULL;
1369  nulls[i] = true;
1370  }
1371  else if (value)
1372  {
1373  values[i] = (att->func) (att, -1, value, false);
1374  nulls[i] = false;
1375  }
1376  else
1377  {
1378  /*
1379  * No attribute for this column in the object.
1380  *
1381  * If we are parsing a composite type in an array, a likely
1382  * cause is that the function contained something like "[[123,
1383  * 'foo']]". Before PostgreSQL 10, that was interpreted as an
1384  * array, with a composite type (123, 'foo') in it. But now
1385  * it's interpreted as a two-dimensional array, and we try to
1386  * interpret "123" as the composite type. See also similar
1387  * heuristic in PLyObject_ToDatum().
1388  */
1389  ereport(ERROR,
1390  (errcode(ERRCODE_UNDEFINED_COLUMN),
1391  errmsg("attribute \"%s\" does not exist in Python object", key),
1392  inarray ?
1393  errhint("To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".") :
1394  errhint("To return null in a column, let the returned object have an attribute named after column with value None.")));
1395  }
1396 
1397  Py_XDECREF(value);
1398  value = NULL;
1399  }
1400  PG_CATCH();
1401  {
1402  Py_XDECREF(value);
1403  PG_RE_THROW();
1404  }
1405  PG_END_TRY();
1406  }
1407 
1408  tuple = heap_form_tuple(desc, values, nulls);
1409  result = heap_copy_tuple_as_datum(tuple, desc);
1410  heap_freetuple(tuple);
1411 
1412  pfree(values);
1413  pfree(nulls);
1414 
1415  return result;
1416 }
void PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:181
int errhint(const char *fmt,...)
Definition: elog.c:987
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
int errcode(int sqlerrcode)
Definition: elog.c:575
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
int natts
Definition: tupdesc.h:73
PLyObToDatumFunc func
Definition: plpy_typeio.h:57
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
static struct @121 value
PLyTypeOutput out
Definition: plpy_typeio.h:87
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ereport(elevel, rest)
Definition: elog.h:122
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:659
uintptr_t Datum
Definition: postgres.h:372
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:681
int is_rowtype
Definition: plpy_typeio.h:93
PLyObToTuple r
Definition: plpy_typeio.h:78
#define PG_RE_THROW()
Definition: elog.h:314
static Datum values[MAXATTR]
Definition: bootstrap.c:164
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:493
PLyObToDatum * atts
Definition: plpy_typeio.h:71
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
static PyObject * PLyInt_FromInt16 ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 577 of file plpy_typeio.c.

References DatumGetInt16.

Referenced by PLy_input_datum_func2().

578 {
579  return PyInt_FromLong(DatumGetInt16(d));
580 }
#define DatumGetInt16(X)
Definition: postgres.h:450
static PyObject * PLyInt_FromInt32 ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 583 of file plpy_typeio.c.

References DatumGetInt32.

Referenced by PLy_input_datum_func2().

584 {
585  return PyInt_FromLong(DatumGetInt32(d));
586 }
#define DatumGetInt32(X)
Definition: postgres.h:478
static PyObject * PLyList_FromArray ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 631 of file plpy_typeio.c.

References ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, ARR_NULLBITMAP, Assert, DatumGetArrayTypeP, PLyDatumToOb::elm, MAXDIM, and PLyList_FromArray_recurse().

Referenced by PLy_input_datum_func2().

632 {
633  ArrayType *array = DatumGetArrayTypeP(d);
634  PLyDatumToOb *elm = arg->elm;
635  int ndim;
636  int *dims;
637  char *dataptr;
638  bits8 *bitmap;
639  int bitmask;
640 
641  if (ARR_NDIM(array) == 0)
642  return PyList_New(0);
643 
644  /* Array dimensions and left bounds */
645  ndim = ARR_NDIM(array);
646  dims = ARR_DIMS(array);
647  Assert(ndim < MAXDIM);
648 
649  /*
650  * We iterate the SQL array in the physical order it's stored in the
651  * datum. For example, for a 3-dimensional array the order of iteration
652  * would be the following: [0,0,0] elements through [0,0,k], then [0,1,0]
653  * through [0,1,k] till [0,m,k], then [1,0,0] through [1,0,k] till
654  * [1,m,k], and so on.
655  *
656  * In Python, there are no multi-dimensional lists as such, but they are
657  * represented as a list of lists. So a 3-d array of [n,m,k] elements is a
658  * list of n m-element arrays, each element of which is k-element array.
659  * PLyList_FromArray_recurse() builds the Python list for a single
660  * dimension, and recurses for the next inner dimension.
661  */
662  dataptr = ARR_DATA_PTR(array);
663  bitmap = ARR_NULLBITMAP(array);
664  bitmask = 1;
665 
666  return PLyList_FromArray_recurse(elm, dims, ndim, 0,
667  &dataptr, &bitmap, &bitmask);
668 }
#define MAXDIM
Definition: c.h:413
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
struct PLyDatumToOb * elm
Definition: plpy_typeio.h:30
uint8 bits8
Definition: c.h:265
#define Assert(condition)
Definition: c.h:681
#define ARR_NDIM(a)
Definition: array.h:275
static PyObject * PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim, char **dataptr_p, bits8 **bitmap_p, int *bitmask_p)
Definition: plpy_typeio.c:671
#define ARR_NULLBITMAP(a)
Definition: array.h:285
#define DatumGetArrayTypeP(X)
Definition: array.h:246
static PyObject * PLyList_FromArray_recurse ( PLyDatumToOb elm,
int *  dims,
int  ndim,
int  dim,
char **  dataptr_p,
bits8 **  bitmap_p,
int *  bitmask_p 
)
static

Definition at line 671 of file plpy_typeio.c.

References att_addlength_pointer, att_align_nominal, fetch_att, PLyDatumToOb::func, i, sort-test::list, PLyDatumToOb::typalign, PLyDatumToOb::typbyval, and PLyDatumToOb::typlen.

Referenced by PLyList_FromArray().

673 {
674  int i;
675  PyObject *list;
676 
677  list = PyList_New(dims[dim]);
678 
679  if (dim < ndim - 1)
680  {
681  /* Outer dimension. Recurse for each inner slice. */
682  for (i = 0; i < dims[dim]; i++)
683  {
684  PyObject *sublist;
685 
686  sublist = PLyList_FromArray_recurse(elm, dims, ndim, dim + 1,
687  dataptr_p, bitmap_p, bitmask_p);
688  PyList_SET_ITEM(list, i, sublist);
689  }
690  }
691  else
692  {
693  /*
694  * Innermost dimension. Fill the list with the values from the array
695  * for this slice.
696  */
697  char *dataptr = *dataptr_p;
698  bits8 *bitmap = *bitmap_p;
699  int bitmask = *bitmask_p;
700 
701  for (i = 0; i < dims[dim]; i++)
702  {
703  /* checking for NULL */
704  if (bitmap && (*bitmap & bitmask) == 0)
705  {
706  Py_INCREF(Py_None);
707  PyList_SET_ITEM(list, i, Py_None);
708  }
709  else
710  {
711  Datum itemvalue;
712 
713  itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen);
714  PyList_SET_ITEM(list, i, elm->func(elm, itemvalue));
715  dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr);
716  dataptr = (char *) att_align_nominal(dataptr, elm->typalign);
717  }
718 
719  /* advance bitmap pointer if any */
720  if (bitmap)
721  {
722  bitmask <<= 1;
723  if (bitmask == 0x100 /* (1<<8) */ )
724  {
725  bitmap++;
726  bitmask = 1;
727  }
728  }
729  }
730 
731  *dataptr_p = dataptr;
732  *bitmap_p = bitmap;
733  *bitmask_p = bitmask;
734  }
735 
736  return list;
737 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
PLyDatumToObFunc func
Definition: plpy_typeio.h:21
int16 typlen
Definition: plpy_typeio.h:28
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
uint8 bits8
Definition: c.h:265
uintptr_t Datum
Definition: postgres.h:372
tuple list
Definition: sort-test.py:11
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
int i
static PyObject * PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim, char **dataptr_p, bits8 **bitmap_p, int *bitmask_p)
Definition: plpy_typeio.c:671
static PyObject * PLyLong_FromInt64 ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 589 of file plpy_typeio.c.

References DatumGetInt64.

Referenced by PLy_input_datum_func2().

590 {
591  /* on 32 bit platforms "long" may be too small */
592  if (sizeof(int64) > sizeof(long))
593  return PyLong_FromLongLong(DatumGetInt64(d));
594  else
595  return PyLong_FromLong(DatumGetInt64(d));
596 }
#define DatumGetInt64(X)
Definition: postgres.h:613
static PyObject * PLyLong_FromOid ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 599 of file plpy_typeio.c.

References DatumGetObjectId.

Referenced by PLy_input_datum_func2().

600 {
601  return PyLong_FromUnsignedLong(DatumGetObjectId(d));
602 }
#define DatumGetObjectId(X)
Definition: postgres.h:506
static Datum PLyMapping_ToComposite ( PLyTypeInfo info,
TupleDesc  desc,
PyObject *  mapping 
)
static

Definition at line 1165 of file plpy_typeio.c.

References Assert, PLyObToTuple::atts, ereport, errcode(), errhint(), errmsg(), ERROR, PLyObToDatum::func, heap_copy_tuple_as_datum(), heap_form_tuple(), heap_freetuple(), i, PLyTypeInfo::is_rowtype, NameStr, tupleDesc::natts, PLyTypeInfo::out, palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_output_tuple_funcs(), PLyTypeOutput::r, TupleDescAttr, value, and values.

Referenced by PLyObject_ToCompositeDatum().

1166 {
1167  Datum result;
1168  HeapTuple tuple;
1169  Datum *values;
1170  bool *nulls;
1171  volatile int i;
1172 
1173  Assert(PyMapping_Check(mapping));
1174 
1175  if (info->is_rowtype == 2)
1176  PLy_output_tuple_funcs(info, desc);
1177  Assert(info->is_rowtype == 1);
1178 
1179  /* Build tuple */
1180  values = palloc(sizeof(Datum) * desc->natts);
1181  nulls = palloc(sizeof(bool) * desc->natts);
1182  for (i = 0; i < desc->natts; ++i)
1183  {
1184  char *key;
1185  PyObject *volatile value;
1186  PLyObToDatum *att;
1187  Form_pg_attribute attr = TupleDescAttr(desc, i);
1188 
1189  if (attr->attisdropped)
1190  {
1191  values[i] = (Datum) 0;
1192  nulls[i] = true;
1193  continue;
1194  }
1195 
1196  key = NameStr(attr->attname);
1197  value = NULL;
1198  att = &info->out.r.atts[i];
1199  PG_TRY();
1200  {
1201  value = PyMapping_GetItemString(mapping, key);
1202  if (value == Py_None)
1203  {
1204  values[i] = (Datum) NULL;
1205  nulls[i] = true;
1206  }
1207  else if (value)
1208  {
1209  values[i] = (att->func) (att, -1, value, false);
1210  nulls[i] = false;
1211  }
1212  else
1213  ereport(ERROR,
1214  (errcode(ERRCODE_UNDEFINED_COLUMN),
1215  errmsg("key \"%s\" not found in mapping", key),
1216  errhint("To return null in a column, "
1217  "add the value None to the mapping with the key named after the column.")));
1218 
1219  Py_XDECREF(value);
1220  value = NULL;
1221  }
1222  PG_CATCH();
1223  {
1224  Py_XDECREF(value);
1225  PG_RE_THROW();
1226  }
1227  PG_END_TRY();
1228  }
1229 
1230  tuple = heap_form_tuple(desc, values, nulls);
1231  result = heap_copy_tuple_as_datum(tuple, desc);
1232  heap_freetuple(tuple);
1233 
1234  pfree(values);
1235  pfree(nulls);
1236 
1237  return result;
1238 }
void PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:181
int errhint(const char *fmt,...)
Definition: elog.c:987
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
int errcode(int sqlerrcode)
Definition: elog.c:575
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
int natts
Definition: tupdesc.h:73
PLyObToDatumFunc func
Definition: plpy_typeio.h:57
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
static struct @121 value
PLyTypeOutput out
Definition: plpy_typeio.h:87
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ereport(elevel, rest)
Definition: elog.h:122
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:659
uintptr_t Datum
Definition: postgres.h:372
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:681
int is_rowtype
Definition: plpy_typeio.h:93
PLyObToTuple r
Definition: plpy_typeio.h:78
#define PG_RE_THROW()
Definition: elog.h:314
static Datum values[MAXATTR]
Definition: bootstrap.c:164
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:493
PLyObToDatum * atts
Definition: plpy_typeio.h:71
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
char* PLyObject_AsString ( PyObject *  plrv)

Definition at line 850 of file plpy_typeio.c.

References elog, ereport, errcode(), errmsg(), ERROR, pg_verifymbstr(), PLy_elog(), PLyUnicode_Bytes(), pstrdup(), PyBytes_AsString, and PyBytes_Size.

Referenced by PLyObject_ToDatum().

851 {
852  PyObject *plrv_bo;
853  char *plrv_sc;
854  size_t plen;
855  size_t slen;
856 
857  if (PyUnicode_Check(plrv))
858  plrv_bo = PLyUnicode_Bytes(plrv);
859  else if (PyFloat_Check(plrv))
860  {
861  /* use repr() for floats, str() is lossy */
862 #if PY_MAJOR_VERSION >= 3
863  PyObject *s = PyObject_Repr(plrv);
864 
865  plrv_bo = PLyUnicode_Bytes(s);
866  Py_XDECREF(s);
867 #else
868  plrv_bo = PyObject_Repr(plrv);
869 #endif
870  }
871  else
872  {
873 #if PY_MAJOR_VERSION >= 3
874  PyObject *s = PyObject_Str(plrv);
875 
876  plrv_bo = PLyUnicode_Bytes(s);
877  Py_XDECREF(s);
878 #else
879  plrv_bo = PyObject_Str(plrv);
880 #endif
881  }
882  if (!plrv_bo)
883  PLy_elog(ERROR, "could not create string representation of Python object");
884 
885  plrv_sc = pstrdup(PyBytes_AsString(plrv_bo));
886  plen = PyBytes_Size(plrv_bo);
887  slen = strlen(plrv_sc);
888 
889  Py_XDECREF(plrv_bo);
890 
891  if (slen < plen)
892  ereport(ERROR,
893  (errcode(ERRCODE_DATATYPE_MISMATCH),
894  errmsg("could not convert Python object into cstring: Python string representation appears to contain null bytes")));
895  else if (slen > plen)
896  elog(ERROR, "could not convert Python object into cstring: Python string longer than reported length");
897  pg_verifymbstr(plrv_sc, slen, false);
898 
899  return plrv_sc;
900 }
char * pstrdup(const char *in)
Definition: mcxt.c:1076
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PyBytes_AsString
Definition: plpython.h:84
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define PyBytes_Size
Definition: plpython.h:86
PyObject * PLyUnicode_Bytes(PyObject *unicode)
Definition: plpy_util.c:26
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1866
#define elog
Definition: elog.h:219
static PyObject * PLyObject_FromTransform ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 625 of file plpy_typeio.c.

References DatumGetPointer, FunctionCall1, and PLyDatumToOb::typtransform.

Referenced by PLy_input_datum_func2().

626 {
627  return (PyObject *) DatumGetPointer(FunctionCall1(&arg->typtransform, d));
628 }
FmgrInfo typtransform
Definition: plpy_typeio.h:23
#define DatumGetPointer(X)
Definition: postgres.h:555
#define FunctionCall1(flinfo, arg1)
Definition: fmgr.h:603
static Datum PLyObject_ToBool ( PLyObToDatum arg,
int32  typmod,
PyObject *  plrv,
bool  inarray 
)
static

Definition at line 746 of file plpy_typeio.c.

References Assert, BoolGetDatum, domain_check(), FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, get_typtype(), PLyObToDatum::typfunc, PLyObToDatum::typoid, and TYPTYPE_DOMAIN.

Referenced by PLy_output_datum_func2().

747 {
748  Datum rv;
749 
750  Assert(plrv != Py_None);
751  rv = BoolGetDatum(PyObject_IsTrue(plrv));
752 
753  if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
754  domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
755 
756  return rv;
757 }
FmgrInfo typfunc
Definition: plpy_typeio.h:58
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
MemoryContext fn_mcxt
Definition: fmgr.h:65
char get_typtype(Oid typid)
Definition: lsyscache.c:2379
uintptr_t Datum
Definition: postgres.h:372
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
Definition: domains.c:326
#define BoolGetDatum(X)
Definition: postgres.h:408
#define Assert(condition)
Definition: c.h:681
void * fn_extra
Definition: fmgr.h:64
static Datum PLyObject_ToBytea ( PLyObToDatum arg,
int32  typmod,
PyObject *  plrv,
bool  inarray 
)
static

Definition at line 765 of file plpy_typeio.c.

References Assert, domain_check(), ERROR, FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, get_typtype(), palloc(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_elog(), PointerGetDatum, PyBytes_AsString, PyBytes_Size, PyObject_Bytes, SET_VARSIZE, PLyObToDatum::typfunc, PLyObToDatum::typoid, TYPTYPE_DOMAIN, VARDATA, and VARHDRSZ.

Referenced by PLy_output_datum_func2().

766 {
767  PyObject *volatile plrv_so = NULL;
768  Datum rv;
769 
770  Assert(plrv != Py_None);
771 
772  plrv_so = PyObject_Bytes(plrv);
773  if (!plrv_so)
774  PLy_elog(ERROR, "could not create bytes representation of Python object");
775 
776  PG_TRY();
777  {
778  char *plrv_sc = PyBytes_AsString(plrv_so);
779  size_t len = PyBytes_Size(plrv_so);
780  size_t size = len + VARHDRSZ;
781  bytea *result = palloc(size);
782 
783  SET_VARSIZE(result, size);
784  memcpy(VARDATA(result), plrv_sc, len);
785  rv = PointerGetDatum(result);
786  }
787  PG_CATCH();
788  {
789  Py_XDECREF(plrv_so);
790  PG_RE_THROW();
791  }
792  PG_END_TRY();
793 
794  Py_XDECREF(plrv_so);
795 
796  if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
797  domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
798 
799  return rv;
800 }
FmgrInfo typfunc
Definition: plpy_typeio.h:58
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
#define VARDATA(PTR)
Definition: postgres.h:303
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define PyObject_Bytes
Definition: plpython.h:87
#define PointerGetDatum(X)
Definition: postgres.h:562
#define VARHDRSZ
Definition: c.h:439
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
char get_typtype(Oid typid)
Definition: lsyscache.c:2379
#define PyBytes_AsString
Definition: plpython.h:84
#define ERROR
Definition: elog.h:43
#define PyBytes_Size
Definition: plpython.h:86
uintptr_t Datum
Definition: postgres.h:372
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
Definition: domains.c:326
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:681
#define PG_RE_THROW()
Definition: elog.h:314
void * fn_extra
Definition: fmgr.h:64
void * palloc(Size size)
Definition: mcxt.c:848
Definition: c.h:433
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
static Datum PLyObject_ToComposite ( PLyObToDatum arg,
int32  typmod,
PyObject *  plrv,
bool  inarray 
)
static

Definition at line 809 of file plpy_typeio.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), CurrentMemoryContext, elog, ERROR, PLyTypeInfo::is_rowtype, lookup_rowtype_tupdesc(), MemoryContextDelete(), MemSet, PLy_typeinfo_init(), PLyObject_ToCompositeDatum(), ReleaseTupleDesc, PLyObToDatum::typmod, and PLyObToDatum::typoid.

Referenced by PLy_output_datum_func2().

810 {
811  Datum rv;
812  PLyTypeInfo info;
813  TupleDesc desc;
814  MemoryContext cxt;
815 
816  if (typmod != -1)
817  elog(ERROR, "received unnamed record type as input");
818 
819  /* Create a dummy PLyTypeInfo */
821  "PL/Python temp context",
823  MemSet(&info, 0, sizeof(PLyTypeInfo));
824  PLy_typeinfo_init(&info, cxt);
825  /* Mark it as needing output routines lookup */
826  info.is_rowtype = 2;
827 
828  desc = lookup_rowtype_tupdesc(arg->typoid, arg->typmod);
829 
830  /*
831  * This will set up the dummy PLyTypeInfo's output conversion routines,
832  * since we left is_rowtype as 2. A future optimization could be caching
833  * that info instead of looking it up every time a tuple is returned from
834  * the function.
835  */
836  rv = PLyObject_ToCompositeDatum(&info, desc, plrv, inarray);
837 
838  ReleaseTupleDesc(desc);
839 
840  MemoryContextDelete(cxt);
841 
842  return rv;
843 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
void PLy_typeinfo_init(PLyTypeInfo *arg, MemoryContext mcxt)
Definition: plpy_typeio.c:70
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1579
#define MemSet(start, val, len)
Definition: c.h:863
int32 typmod
Definition: plpy_typeio.h:61
#define ERROR
Definition: elog.h:43
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
int is_rowtype
Definition: plpy_typeio.h:93
Datum PLyObject_ToCompositeDatum(PLyTypeInfo *info, TupleDesc desc, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:346
#define elog
Definition: elog.h:219
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:115
Datum PLyObject_ToCompositeDatum ( PLyTypeInfo info,
TupleDesc  desc,
PyObject *  plrv,
bool  inarray 
)

Definition at line 346 of file plpy_typeio.c.

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

Referenced by PLy_exec_function(), and PLyObject_ToComposite().

347 {
348  Datum datum;
349 
350  if (PyString_Check(plrv) || PyUnicode_Check(plrv))
351  datum = PLyString_ToComposite(info, desc, plrv, inarray);
352  else if (PySequence_Check(plrv))
353  /* composite type as sequence (tuple, list etc) */
354  datum = PLySequence_ToComposite(info, desc, plrv);
355  else if (PyMapping_Check(plrv))
356  /* composite type as mapping (currently only dict) */
357  datum = PLyMapping_ToComposite(info, desc, plrv);
358  else
359  /* returned as smth, must provide method __getattr__(name) */
360  datum = PLyGenericObject_ToComposite(info, desc, plrv, inarray);
361 
362  return datum;
363 }
static Datum PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string, bool inarray)
Definition: plpy_typeio.c:1131
uintptr_t Datum
Definition: postgres.h:372
static Datum PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object, bool inarray)
Definition: plpy_typeio.c:1331
static Datum PLyMapping_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *mapping)
Definition: plpy_typeio.c:1165
static Datum PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence)
Definition: plpy_typeio.c:1242
static Datum PLyObject_ToDatum ( PLyObToDatum arg,
int32  typmod,
PyObject *  plrv,
bool  inarray 
)
static

Definition at line 908 of file plpy_typeio.c.

References Assert, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, FmgrInfo::fn_oid, InputFunctionCall(), PLyObject_AsString(), PLyObToDatum::typfunc, and PLyObToDatum::typioparam.

Referenced by PLy_output_datum_func2(), and PLyString_ToComposite().

909 {
910  char *str;
911 
912  Assert(plrv != Py_None);
913 
914  str = PLyObject_AsString(plrv);
915 
916  /*
917  * If we are parsing a composite type within an array, and the string
918  * isn't a valid record literal, there's a high chance that the function
919  * did something like:
920  *
921  * CREATE FUNCTION .. RETURNS comptype[] AS $$ return [['foo', 'bar']] $$
922  * LANGUAGE plpython;
923  *
924  * Before PostgreSQL 10, that was interpreted as a single-dimensional
925  * array, containing record ('foo', 'bar'). PostgreSQL 10 added support
926  * for multi-dimensional arrays, and it is now interpreted as a
927  * two-dimensional array, containing two records, 'foo', and 'bar'.
928  * record_in() will throw an error, because "foo" is not a valid record
929  * literal.
930  *
931  * To make that less confusing to users who are upgrading from older
932  * versions, try to give a hint in the typical instances of that. If we
933  * are parsing an array of composite types, and we see a string literal
934  * that is not a valid record literal, give a hint. We only want to give
935  * the hint in the narrow case of a malformed string literal, not any
936  * error from record_in(), so check for that case here specifically.
937  *
938  * This check better match the one in record_in(), so that we don't forbid
939  * literals that are actually valid!
940  */
941  if (inarray && arg->typfunc.fn_oid == F_RECORD_IN)
942  {
943  char *ptr = str;
944 
945  /* Allow leading whitespace */
946  while (*ptr && isspace((unsigned char) *ptr))
947  ptr++;
948  if (*ptr++ != '(')
949  ereport(ERROR,
950  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
951  errmsg("malformed record literal: \"%s\"", str),
952  errdetail("Missing left parenthesis."),
953  errhint("To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".")));
954  }
955 
956  return InputFunctionCall(&arg->typfunc,
957  str,
958  arg->typioparam,
959  typmod);
960 }
FmgrInfo typfunc
Definition: plpy_typeio.h:58
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
char * PLyObject_AsString(PyObject *plrv)
Definition: plpy_typeio.c:850
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1618
Oid fn_oid
Definition: fmgr.h:59
#define Assert(condition)
Definition: c.h:681
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Datum PLyObject_ToTransform ( PLyObToDatum arg,
int32  typmod,
PyObject *  plrv,
bool  inarray 
)
static

Definition at line 964 of file plpy_typeio.c.

References FunctionCall1, PointerGetDatum, and PLyObToDatum::typtransform.

Referenced by PLy_output_datum_func2().

965 {
966  return FunctionCall1(&arg->typtransform, PointerGetDatum(plrv));
967 }
#define PointerGetDatum(X)
Definition: postgres.h:562
#define FunctionCall1(flinfo, arg1)
Definition: fmgr.h:603
FmgrInfo typtransform
Definition: plpy_typeio.h:59
static Datum PLySequence_ToArray ( PLyObToDatum arg,
int32  typmod,
PyObject *  plrv,
bool  inarray 
)
static

Definition at line 971 of file plpy_typeio.c.

References Assert, construct_md_array(), domain_check(), PLyObToDatum::elm, ERROR, FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, get_base_element_type(), get_typtype(), i, MaxAllocSize, MAXDIM, next, palloc(), PLy_elog(), PLySequence_ToArray_recurse(), PointerGetDatum, PLyObToDatum::typalign, PLyObToDatum::typbyval, PLyObToDatum::typfunc, PLyObToDatum::typlen, PLyObToDatum::typoid, and TYPTYPE_DOMAIN.

Referenced by PLy_output_datum_func2().

972 {
973  ArrayType *array;
974  int i;
975  Datum *elems;
976  bool *nulls;
977  int64 len;
978  int ndim;
979  int dims[MAXDIM];
980  int lbs[MAXDIM];
981  int currelem;
982  Datum rv;
983  PyObject *pyptr = plrv;
984  PyObject *next;
985 
986  Assert(plrv != Py_None);
987 
988  /*
989  * Determine the number of dimensions, and their sizes.
990  */
991  ndim = 0;
992  len = 1;
993 
994  Py_INCREF(plrv);
995 
996  for (;;)
997  {
998  if (!PyList_Check(pyptr))
999  break;
1000 
1001  if (ndim == MAXDIM)
1002  PLy_elog(ERROR, "number of array dimensions exceeds the maximum allowed (%d)", MAXDIM);
1003 
1004  dims[ndim] = PySequence_Length(pyptr);
1005  if (dims[ndim] < 0)
1006  PLy_elog(ERROR, "could not determine sequence length for function return value");
1007 
1008  if (dims[ndim] > MaxAllocSize)
1009  PLy_elog(ERROR, "array size exceeds the maximum allowed");
1010 
1011  len *= dims[ndim];
1012  if (len > MaxAllocSize)
1013  PLy_elog(ERROR, "array size exceeds the maximum allowed");
1014 
1015  if (dims[ndim] == 0)
1016  {
1017  /* empty sequence */
1018  break;
1019  }
1020 
1021  ndim++;
1022 
1023  next = PySequence_GetItem(pyptr, 0);
1024  Py_XDECREF(pyptr);
1025  pyptr = next;
1026  }
1027  Py_XDECREF(pyptr);
1028 
1029  /*
1030  * Check for zero dimensions. This happens if the object is a tuple or a
1031  * string, rather than a list, or is not a sequence at all. We don't map
1032  * tuples or strings to arrays in general, but in the first level, be
1033  * lenient, for historical reasons. So if the object is a sequence of any
1034  * kind, treat it as a one-dimensional array.
1035  */
1036  if (ndim == 0)
1037  {
1038  if (!PySequence_Check(plrv))
1039  PLy_elog(ERROR, "return value of function with array return type is not a Python sequence");
1040 
1041  ndim = 1;
1042  len = dims[0] = PySequence_Length(plrv);
1043  }
1044 
1045  /*
1046  * Traverse the Python lists, in depth-first order, and collect all the
1047  * elements at the bottom level into 'elems'/'nulls' arrays.
1048  */
1049  elems = palloc(sizeof(Datum) * len);
1050  nulls = palloc(sizeof(bool) * len);
1051  currelem = 0;
1052  PLySequence_ToArray_recurse(arg->elm, plrv,
1053  dims, ndim, 0,
1054  elems, nulls, &currelem);
1055 
1056  for (i = 0; i < ndim; i++)
1057  lbs[i] = 1;
1058 
1059  array = construct_md_array(elems,
1060  nulls,
1061  ndim,
1062  dims,
1063  lbs,
1065  arg->elm->typlen,
1066  arg->elm->typbyval,
1067  arg->elm->typalign);
1068 
1069  /*
1070  * If the result type is a domain of array, the resulting array must be
1071  * checked.
1072  */
1073  rv = PointerGetDatum(array);
1074  if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
1075  domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
1076  return rv;
1077 }
FmgrInfo typfunc
Definition: plpy_typeio.h:58
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
static int32 next
Definition: blutils.c:210
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define MAXDIM
Definition: c.h:413
#define PointerGetDatum(X)
Definition: postgres.h:562
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
char get_typtype(Oid typid)
Definition: lsyscache.c:2379
#define ERROR
Definition: elog.h:43
#define MaxAllocSize
Definition: memutils.h:40
uintptr_t Datum
Definition: postgres.h:372
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
Definition: domains.c:326
#define Assert(condition)
Definition: c.h:681
void * fn_extra
Definition: fmgr.h:64
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2557
struct PLyObToDatum * elm
Definition: plpy_typeio.h:66
void * palloc(Size size)
Definition: mcxt.c:848
int i
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3314
static void PLySequence_ToArray_recurse(PLyObToDatum *elm, PyObject *list, int *dims, int ndim, int dim, Datum *elems, bool *nulls, int *currelem)
Definition: plpy_typeio.c:1084
int16 typlen
Definition: plpy_typeio.h:64
static void PLySequence_ToArray_recurse ( PLyObToDatum elm,
PyObject *  list,
int *  dims,
int  ndim,
int  dim,
Datum elems,
bool nulls,
int *  currelem 
)
static

Definition at line 1084 of file plpy_typeio.c.

References ereport, errdetail(), errmsg(), ERROR, PLyObToDatum::func, and i.

Referenced by PLySequence_ToArray().

1087 {
1088  int i;
1089 
1090  if (PySequence_Length(list) != dims[dim])
1091  ereport(ERROR,
1092  (errmsg("wrong length of inner sequence: has length %d, but %d was expected",
1093  (int) PySequence_Length(list), dims[dim]),
1094  (errdetail("To construct a multidimensional array, the inner sequences must all have the same length."))));
1095 
1096  if (dim < ndim - 1)
1097  {
1098  for (i = 0; i < dims[dim]; i++)
1099  {
1100  PyObject *sublist = PySequence_GetItem(list, i);
1101 
1102  PLySequence_ToArray_recurse(elm, sublist, dims, ndim, dim + 1,
1103  elems, nulls, currelem);
1104  Py_XDECREF(sublist);
1105  }
1106  }
1107  else
1108  {
1109  for (i = 0; i < dims[dim]; i++)
1110  {
1111  PyObject *obj = PySequence_GetItem(list, i);
1112 
1113  if (obj == Py_None)
1114  {
1115  nulls[*currelem] = true;
1116  elems[*currelem] = (Datum) 0;
1117  }
1118  else
1119  {
1120  nulls[*currelem] = false;
1121  elems[*currelem] = elm->func(elm, -1, obj, true);
1122  }
1123  Py_XDECREF(obj);
1124  (*currelem)++;
1125  }
1126  }
1127 }
PLyObToDatumFunc func
Definition: plpy_typeio.h:57
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:372
tuple list
Definition: sort-test.py:11
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
static void PLySequence_ToArray_recurse(PLyObToDatum *elm, PyObject *list, int *dims, int ndim, int dim, Datum *elems, bool *nulls, int *currelem)
Definition: plpy_typeio.c:1084
static Datum PLySequence_ToComposite ( PLyTypeInfo info,
TupleDesc  desc,
PyObject *  sequence 
)
static

Definition at line 1242 of file plpy_typeio.c.

References Assert, PLyObToTuple::atts, ereport, errcode(), errmsg(), ERROR, PLyObToDatum::func, heap_copy_tuple_as_datum(), heap_form_tuple(), heap_freetuple(), i, idx(), PLyTypeInfo::is_rowtype, tupleDesc::natts, PLyTypeInfo::out, palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_output_tuple_funcs(), PLyTypeOutput::r, TupleDescAttr, value, and values.

Referenced by PLyObject_ToCompositeDatum().

1243 {
1244  Datum result;
1245  HeapTuple tuple;
1246  Datum *values;
1247  bool *nulls;
1248  volatile int idx;
1249  volatile int i;
1250 
1251  Assert(PySequence_Check(sequence));
1252 
1253  /*
1254  * Check that sequence length is exactly same as PG tuple's. We actually
1255  * can ignore exceeding items or assume missing ones as null but to avoid
1256  * plpython developer's errors we are strict here
1257  */
1258  idx = 0;
1259  for (i = 0; i < desc->natts; i++)
1260  {
1261  if (!TupleDescAttr(desc, i)->attisdropped)
1262  idx++;
1263  }
1264  if (PySequence_Length(sequence) != idx)
1265  ereport(ERROR,
1266  (errcode(ERRCODE_DATATYPE_MISMATCH),
1267  errmsg("length of returned sequence did not match number of columns in row")));
1268 
1269  if (info->is_rowtype == 2)
1270  PLy_output_tuple_funcs(info, desc);
1271  Assert(info->is_rowtype == 1);
1272 
1273  /* Build tuple */
1274  values = palloc(sizeof(Datum) * desc->natts);
1275  nulls = palloc(sizeof(bool) * desc->natts);
1276  idx = 0;
1277  for (i = 0; i < desc->natts; ++i)
1278  {
1279  PyObject *volatile value;
1280  PLyObToDatum *att;
1281 
1282  if (TupleDescAttr(desc, i)->attisdropped)
1283  {
1284  values[i] = (Datum) 0;
1285  nulls[i] = true;
1286  continue;
1287  }
1288 
1289  value = NULL;
1290  att = &info->out.r.atts[i];
1291  PG_TRY();
1292  {
1293  value = PySequence_GetItem(sequence, idx);
1294  Assert(value);
1295  if (value == Py_None)
1296  {
1297  values[i] = (Datum) NULL;
1298  nulls[i] = true;
1299  }
1300  else if (value)
1301  {
1302  values[i] = (att->func) (att, -1, value, false);
1303  nulls[i] = false;
1304  }
1305 
1306  Py_XDECREF(value);
1307  value = NULL;
1308  }
1309  PG_CATCH();
1310  {
1311  Py_XDECREF(value);
1312  PG_RE_THROW();
1313  }
1314  PG_END_TRY();
1315 
1316  idx++;
1317  }
1318 
1319  tuple = heap_form_tuple(desc, values, nulls);
1320  result = heap_copy_tuple_as_datum(tuple, desc);
1321  heap_freetuple(tuple);
1322 
1323  pfree(values);
1324  pfree(nulls);
1325 
1326  return result;
1327 }
void PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:181
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
int natts
Definition: tupdesc.h:73
PLyObToDatumFunc func
Definition: plpy_typeio.h:57
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
static struct @121 value
PLyTypeOutput out
Definition: plpy_typeio.h:87
#define ereport(elevel, rest)
Definition: elog.h:122
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:659
uintptr_t Datum
Definition: postgres.h:372
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:681
int is_rowtype
Definition: plpy_typeio.h:93
PLyObToTuple r
Definition: plpy_typeio.h:78
#define PG_RE_THROW()
Definition: elog.h:314
static Datum values[MAXATTR]
Definition: bootstrap.c:164
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
PLyObToDatum * atts
Definition: plpy_typeio.h:71
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
static PyObject * PLyString_FromDatum ( PLyDatumToOb arg,
Datum  d 
)
static

Definition at line 615 of file plpy_typeio.c.

References OutputFunctionCall(), pfree(), and PLyDatumToOb::typfunc.

Referenced by PLy_input_datum_func2().

616 {
617  char *x = OutputFunctionCall(&arg->typfunc, d);
618  PyObject *r = PyString_FromString(x);
619 
620  pfree(x);
621  return r;
622 }
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1662
void pfree(void *pointer)
Definition: mcxt.c:949
FmgrInfo typfunc
Definition: plpy_typeio.h:22
static Datum PLyString_ToComposite ( PLyTypeInfo info,
TupleDesc  desc,
PyObject *  string,
bool  inarray 
)
static

Definition at line 1131 of file plpy_typeio.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), PLyExecutionContext::curr_proc, CurrentMemoryContext, PLyTypeOutput::d, elog, ERROR, HeapTupleIsValid, PLyProcedure::langid, PLyTypeInfo::mcxt, MemoryContextDelete(), MemSet, ObjectIdGetDatum, PLyTypeInfo::out, PLy_current_execution_context(), PLy_output_datum_func2(), PLy_typeinfo_init(), PLyObject_ToDatum(), ReleaseSysCache(), SearchSysCache1(), tupleDesc::tdtypeid, tupleDesc::tdtypmod, PLyProcedure::trftypes, and TYPEOID.

Referenced by PLyObject_ToCompositeDatum().

1132 {
1133  Datum result;
1134  HeapTuple typeTup;
1135  PLyTypeInfo locinfo;
1137  MemoryContext cxt;
1138 
1139  /* Create a dummy PLyTypeInfo */
1141  "PL/Python temp context",
1143  MemSet(&locinfo, 0, sizeof(PLyTypeInfo));
1144  PLy_typeinfo_init(&locinfo, cxt);
1145 
1146  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(desc->tdtypeid));
1147  if (!HeapTupleIsValid(typeTup))
1148  elog(ERROR, "cache lookup failed for type %u", desc->tdtypeid);
1149 
1150  PLy_output_datum_func2(&locinfo.out.d, locinfo.mcxt, typeTup,
1151  exec_ctx->curr_proc->langid,
1152  exec_ctx->curr_proc->trftypes);
1153 
1154  ReleaseSysCache(typeTup);
1155 
1156  result = PLyObject_ToDatum(&locinfo.out.d, desc->tdtypmod, string, inarray);
1157 
1158  MemoryContextDelete(cxt);
1159 
1160  return result;
1161 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
Oid tdtypeid
Definition: tupdesc.h:74
void PLy_typeinfo_init(PLyTypeInfo *arg, MemoryContext mcxt)
Definition: plpy_typeio.c:70
#define MemSet(start, val, len)
Definition: c.h:863
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:398
int32 tdtypmod
Definition: tupdesc.h:75
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
PLyObToDatum d
Definition: plpy_typeio.h:77
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
PLyTypeOutput out
Definition: plpy_typeio.h:87
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
PLyProcedure * curr_proc
Definition: plpy_main.h:20
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
MemoryContext mcxt
Definition: plpy_typeio.h:100
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static void PLy_output_datum_func2(PLyObToDatum *arg, MemoryContext arg_mcxt, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:366
#define elog
Definition: elog.h:219
static Datum PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:908