PostgreSQL Source Code  git master
plpy_typeio.h File Reference
#include "access/htup.h"
#include "fmgr.h"
#include "plpython.h"
#include "utils/typcache.h"
Include dependency graph for plpy_typeio.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PLyScalarToOb
 
struct  PLyArrayToOb
 
struct  PLyTupleToOb
 
struct  PLyTransformToOb
 
struct  PLyDatumToOb
 
struct  PLyObToScalar
 
struct  PLyObToArray
 
struct  PLyObToTuple
 
struct  PLyObToDomain
 
struct  PLyObToTransform
 
struct  PLyObToDatum
 

Typedefs

typedef struct PLyDatumToOb PLyDatumToOb
 
typedef PyObject *(* PLyDatumToObFunc) (PLyDatumToOb *arg, Datum val)
 
typedef struct PLyScalarToOb PLyScalarToOb
 
typedef struct PLyArrayToOb PLyArrayToOb
 
typedef struct PLyTupleToOb PLyTupleToOb
 
typedef struct PLyTransformToOb PLyTransformToOb
 
typedef struct PLyObToDatum PLyObToDatum
 
typedef Datum(* PLyObToDatumFunc) (PLyObToDatum *arg, PyObject *val, bool *isnull, bool inarray)
 
typedef struct PLyObToScalar PLyObToScalar
 
typedef struct PLyObToArray PLyObToArray
 
typedef struct PLyObToTuple PLyObToTuple
 
typedef struct PLyObToDomain PLyObToDomain
 
typedef struct PLyObToTransform PLyObToTransform
 

Functions

PyObject * PLy_input_convert (PLyDatumToOb *arg, Datum val)
 
Datum PLy_output_convert (PLyObToDatum *arg, PyObject *val, bool *isnull)
 
PyObject * PLy_input_from_tuple (PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool include_generated)
 
void PLy_input_setup_func (PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, struct PLyProcedure *proc)
 
void PLy_output_setup_func (PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, struct PLyProcedure *proc)
 
void PLy_input_setup_tuple (PLyDatumToOb *arg, TupleDesc desc, struct PLyProcedure *proc)
 
void PLy_output_setup_tuple (PLyObToDatum *arg, TupleDesc desc, struct PLyProcedure *proc)
 
void PLy_output_setup_record (PLyObToDatum *arg, TupleDesc desc, struct PLyProcedure *proc)
 
char * PLyObject_AsString (PyObject *plrv)
 

Typedef Documentation

◆ PLyArrayToOb

typedef struct PLyArrayToOb PLyArrayToOb

◆ PLyDatumToOb

typedef struct PLyDatumToOb PLyDatumToOb

Definition at line 26 of file plpy_typeio.h.

◆ PLyDatumToObFunc

typedef PyObject*(* PLyDatumToObFunc) (PLyDatumToOb *arg, Datum val)

Definition at line 28 of file plpy_typeio.h.

◆ PLyObToArray

typedef struct PLyObToArray PLyObToArray

◆ PLyObToDatum

typedef struct PLyObToDatum PLyObToDatum

Definition at line 87 of file plpy_typeio.h.

◆ PLyObToDatumFunc

typedef Datum(* PLyObToDatumFunc) (PLyObToDatum *arg, PyObject *val, bool *isnull, bool inarray)

Definition at line 89 of file plpy_typeio.h.

◆ PLyObToDomain

typedef struct PLyObToDomain PLyObToDomain

◆ PLyObToScalar

typedef struct PLyObToScalar PLyObToScalar

◆ PLyObToTransform

◆ PLyObToTuple

typedef struct PLyObToTuple PLyObToTuple

◆ PLyScalarToOb

typedef struct PLyScalarToOb PLyScalarToOb

◆ PLyTransformToOb

◆ PLyTupleToOb

typedef struct PLyTupleToOb PLyTupleToOb

Function Documentation

◆ PLy_input_convert()

PyObject* PLy_input_convert ( PLyDatumToOb arg,
Datum  val 
)

Definition at line 80 of file plpy_typeio.c.

References PLyDatumToOb::func, MemoryContextReset(), MemoryContextSwitchTo(), PLy_current_execution_context(), and PLy_get_scratch_context().

Referenced by PLy_function_build_args().

81 {
82  PyObject *result;
84  MemoryContext scratch_context = PLy_get_scratch_context(exec_ctx);
85  MemoryContext oldcontext;
86 
87  /*
88  * Do the work in the scratch context to avoid leaking memory from the
89  * datatype output function calls. (The individual PLyDatumToObFunc
90  * functions can't reset the scratch context, because they recurse and an
91  * inner one might clobber data an outer one still needs. So we do it
92  * once at the outermost recursion level.)
93  *
94  * We reset the scratch context before, not after, each conversion cycle.
95  * This way we aren't on the hook to release a Python refcount on the
96  * result object in case MemoryContextReset throws an error.
97  */
98  MemoryContextReset(scratch_context);
99 
100  oldcontext = MemoryContextSwitchTo(scratch_context);
101 
102  result = arg->func(arg, val);
103 
104  MemoryContextSwitchTo(oldcontext);
105 
106  return result;
107 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:410
PLyDatumToObFunc func
Definition: plpy_typeio.h:59
long val
Definition: informix.c:664
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
Definition: plpy_main.c:419

◆ PLy_input_from_tuple()

PyObject* PLy_input_from_tuple ( PLyDatumToOb arg,
HeapTuple  tuple,
TupleDesc  desc,
bool  include_generated 
)

Definition at line 133 of file plpy_typeio.c.

References MemoryContextReset(), MemoryContextSwitchTo(), PLy_current_execution_context(), PLy_get_scratch_context(), and PLyDict_FromTuple().

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

134 {
135  PyObject *dict;
137  MemoryContext scratch_context = PLy_get_scratch_context(exec_ctx);
138  MemoryContext oldcontext;
139 
140  /*
141  * As in PLy_input_convert, do the work in the scratch context.
142  */
143  MemoryContextReset(scratch_context);
144 
145  oldcontext = MemoryContextSwitchTo(scratch_context);
146 
147  dict = PLyDict_FromTuple(arg, tuple, desc, include_generated);
148 
149  MemoryContextSwitchTo(oldcontext);
150 
151  return dict;
152 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:410
static PyObject * PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool include_generated)
Definition: plpy_typeio.c:814
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
Definition: plpy_main.c:419

◆ PLy_input_setup_func()

void PLy_input_setup_func ( PLyDatumToOb arg,
MemoryContext  arg_mcxt,
Oid  typeOid,
int32  typmod,
struct PLyProcedure proc 
)

Definition at line 417 of file plpy_typeio.c.

References PLyDatumToOb::array, PLyTupleToOb::atts, check_stack_depth(), TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, PLyArrayToOb::elm, fmgr_info_cxt(), PLyDatumToOb::func, get_transform_fromsql(), getTypeOutputInfo(), INVALID_TUPLEDESC_IDENTIFIER, PLyProcedure::langid, lookup_type_cache(), PLyDatumToOb::mcxt, MemoryContextAllocZero(), PLyTupleToOb::natts, OidIsValid, PLy_input_setup_func(), PLyBool_FromBool(), PLyBytes_FromBytea(), PLyDecimal_FromNumeric(), PLyDict_FromComposite(), PLyFloat_FromFloat4(), PLyFloat_FromFloat8(), PLyInt_FromInt16(), PLyInt_FromInt32(), PLyList_FromArray(), PLyLong_FromInt64(), PLyLong_FromOid(), PLyObject_FromTransform(), PLyString_FromScalar(), PLyTupleToOb::recdesc, PLyDatumToOb::scalar, PLyDatumToOb::transform, PLyProcedure::trftypes, PLyTupleToOb::tupdescid, PLyDatumToOb::tuple, TypeCacheEntry::typalign, PLyDatumToOb::typalign, TypeCacheEntry::typbyval, PLyDatumToOb::typbyval, TYPECACHE_DOMAIN_BASE_INFO, TypeCacheEntry::typelem, PLyTupleToOb::typentry, PLyScalarToOb::typfunc, TypeCacheEntry::typlen, PLyDatumToOb::typlen, PLyDatumToOb::typmod, PLyDatumToOb::typoid, PLyTransformToOb::typtransform, TypeCacheEntry::typtype, and PLyDatumToOb::u.

Referenced by PLy_cursor_plan(), PLy_cursor_query(), PLy_exec_trigger(), PLy_input_setup_func(), PLy_input_setup_tuple(), PLy_procedure_create(), and PLy_spi_execute_fetch_result().

420 {
421  TypeCacheEntry *typentry;
422  char typtype;
423  Oid trfuncid;
424  Oid typoutput;
425  bool typisvarlena;
426 
427  /* Since this is recursive, it could theoretically be driven to overflow */
429 
430  arg->typoid = typeOid;
431  arg->typmod = typmod;
432  arg->mcxt = arg_mcxt;
433 
434  /*
435  * Fetch typcache entry for the target type, asking for whatever info
436  * we'll need later. RECORD is a special case: just treat it as composite
437  * without bothering with the typcache entry.
438  */
439  if (typeOid != RECORDOID)
440  {
441  typentry = lookup_type_cache(typeOid, TYPECACHE_DOMAIN_BASE_INFO);
442  typtype = typentry->typtype;
443  arg->typbyval = typentry->typbyval;
444  arg->typlen = typentry->typlen;
445  arg->typalign = typentry->typalign;
446  }
447  else
448  {
449  typentry = NULL;
450  typtype = TYPTYPE_COMPOSITE;
451  /* hard-wired knowledge about type RECORD: */
452  arg->typbyval = false;
453  arg->typlen = -1;
454  arg->typalign = 'd';
455  }
456 
457  /*
458  * Choose conversion method. Note that transform functions are checked
459  * for composite and scalar types, but not for arrays or domains. This is
460  * somewhat historical, but we'd have a problem allowing them on domains,
461  * since we drill down through all levels of a domain nest without looking
462  * at the intermediate levels at all.
463  */
464  if (typtype == TYPTYPE_DOMAIN)
465  {
466  /* Domain --- we don't care, just recurse down to the base type */
467  PLy_input_setup_func(arg, arg_mcxt,
468  typentry->domainBaseType,
469  typentry->domainBaseTypmod,
470  proc);
471  }
472  else if (typentry &&
473  OidIsValid(typentry->typelem) && typentry->typlen == -1)
474  {
475  /* Standard varlena array (cf. get_element_type) */
476  arg->func = PLyList_FromArray;
477  /* Recursively set up conversion info for the element type */
478  arg->u.array.elm = (PLyDatumToOb *)
479  MemoryContextAllocZero(arg_mcxt, sizeof(PLyDatumToOb));
480  PLy_input_setup_func(arg->u.array.elm, arg_mcxt,
481  typentry->typelem, typmod,
482  proc);
483  }
484  else if ((trfuncid = get_transform_fromsql(typeOid,
485  proc->langid,
486  proc->trftypes)))
487  {
489  fmgr_info_cxt(trfuncid, &arg->u.transform.typtransform, arg_mcxt);
490  }
491  else if (typtype == TYPTYPE_COMPOSITE)
492  {
493  /* Named composite type, or RECORD */
495  /* We'll set up the per-field data later */
496  arg->u.tuple.recdesc = NULL;
497  arg->u.tuple.typentry = typentry;
499  arg->u.tuple.atts = NULL;
500  arg->u.tuple.natts = 0;
501  }
502  else
503  {
504  /* Scalar type, but we have a couple of special cases */
505  switch (typeOid)
506  {
507  case BOOLOID:
508  arg->func = PLyBool_FromBool;
509  break;
510  case FLOAT4OID:
511  arg->func = PLyFloat_FromFloat4;
512  break;
513  case FLOAT8OID:
514  arg->func = PLyFloat_FromFloat8;
515  break;
516  case NUMERICOID:
518  break;
519  case INT2OID:
520  arg->func = PLyInt_FromInt16;
521  break;
522  case INT4OID:
523  arg->func = PLyInt_FromInt32;
524  break;
525  case INT8OID:
526  arg->func = PLyLong_FromInt64;
527  break;
528  case OIDOID:
529  arg->func = PLyLong_FromOid;
530  break;
531  case BYTEAOID:
532  arg->func = PLyBytes_FromBytea;
533  break;
534  default:
535  arg->func = PLyString_FromScalar;
536  getTypeOutputInfo(typeOid, &typoutput, &typisvarlena);
537  fmgr_info_cxt(typoutput, &arg->u.scalar.typfunc, arg_mcxt);
538  break;
539  }
540  }
541 }
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1900
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:615
TupleDesc recdesc
Definition: plpy_typeio.h:43
static PyObject * PLyInt_FromInt32(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:609
PLyDatumToOb * atts
Definition: plpy_typeio.h:48
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2674
FmgrInfo typfunc
Definition: plpy_typeio.h:32
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:549
uint64 tupdescid
Definition: plpy_typeio.h:46
TypeCacheEntry * typentry
Definition: plpy_typeio.h:45
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
#define OidIsValid(objectId)
Definition: c.h:645
bool typbyval
Definition: typcache.h:38
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:146
static PyObject * PLyString_FromScalar(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:641
FmgrInfo typtransform
Definition: plpy_typeio.h:54
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:780
Oid domainBaseType
Definition: typcache.h:105
static PyObject * PLyInt_FromInt16(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:603
PLyArrayToOb array
Definition: plpy_typeio.h:69
static PyObject * PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:563
PLyDatumToObFunc func
Definition: plpy_typeio.h:59
PLyTransformToOb transform
Definition: plpy_typeio.h:71
static PyObject * PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:557
static PyObject * PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:627
void check_stack_depth(void)
Definition: postgres.c:3284
int32 typmod
Definition: plpy_typeio.h:61
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:417
int32 domainBaseTypmod
Definition: typcache.h:106
int16 typlen
Definition: plpy_typeio.h:63
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
static PyObject * PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:569
PLyDatumToOb * elm
Definition: plpy_typeio.h:37
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:140
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
char typtype
Definition: typcache.h:41
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:666
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:621
PLyScalarToOb scalar
Definition: plpy_typeio.h:68
static PyObject * PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:654
char typalign
Definition: typcache.h:39
union PLyDatumToOb::@165 u
MemoryContext mcxt
Definition: plpy_typeio.h:65
PLyTupleToOb tuple
Definition: plpy_typeio.h:70

◆ PLy_input_setup_tuple()

void PLy_input_setup_tuple ( PLyDatumToOb arg,
TupleDesc  desc,
struct PLyProcedure proc 
)

Definition at line 164 of file plpy_typeio.c.

References Assert, PLyTupleToOb::atts, PLyDatumToOb::func, i, PLyDatumToOb::mcxt, MemoryContextAllocZero(), PLyTupleToOb::natts, TupleDescData::natts, pfree(), PLy_input_setup_func(), PLyDict_FromComposite(), PLyTupleToOb::recdesc, PLyDatumToOb::tuple, TupleDescAttr, PLyDatumToOb::typmod, PLyDatumToOb::typoid, and PLyDatumToOb::u.

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

165 {
166  int i;
167 
168  /* We should be working on a previously-set-up struct */
170 
171  /* Save pointer to tupdesc, but only if this is an anonymous record type */
172  if (arg->typoid == RECORDOID && arg->typmod < 0)
173  arg->u.tuple.recdesc = desc;
174 
175  /* (Re)allocate atts array as needed */
176  if (arg->u.tuple.natts != desc->natts)
177  {
178  if (arg->u.tuple.atts)
179  pfree(arg->u.tuple.atts);
180  arg->u.tuple.natts = desc->natts;
181  arg->u.tuple.atts = (PLyDatumToOb *)
183  desc->natts * sizeof(PLyDatumToOb));
184  }
185 
186  /* Fill the atts entries, except for dropped columns */
187  for (i = 0; i < desc->natts; i++)
188  {
189  Form_pg_attribute attr = TupleDescAttr(desc, i);
190  PLyDatumToOb *att = &arg->u.tuple.atts[i];
191 
192  if (attr->attisdropped)
193  continue;
194 
195  if (att->typoid == attr->atttypid && att->typmod == attr->atttypmod)
196  continue; /* already set up this entry */
197 
198  PLy_input_setup_func(att, arg->mcxt,
199  attr->atttypid, attr->atttypmod,
200  proc);
201  }
202 }
TupleDesc recdesc
Definition: plpy_typeio.h:43
PLyDatumToOb * atts
Definition: plpy_typeio.h:48
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:780
void pfree(void *pointer)
Definition: mcxt.c:1056
PLyDatumToObFunc func
Definition: plpy_typeio.h:59
int32 typmod
Definition: plpy_typeio.h:61
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:417
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
#define Assert(condition)
Definition: c.h:739
int i
union PLyDatumToOb::@165 u
MemoryContext mcxt
Definition: plpy_typeio.h:65
PLyTupleToOb tuple
Definition: plpy_typeio.h:70

◆ PLy_output_convert()

Datum PLy_output_convert ( PLyObToDatum arg,
PyObject *  val,
bool isnull 
)

Definition at line 119 of file plpy_typeio.c.

References PLyObToDatum::func.

Referenced by PLy_cursor_plan(), PLy_exec_function(), PLy_modify_tuple(), and PLy_spi_execute_plan().

120 {
121  /* at outer level, we are not considering an array element */
122  return arg->func(arg, val, isnull, false);
123 }
PLyObToDatumFunc func
Definition: plpy_typeio.h:132
long val
Definition: informix.c:664

◆ PLy_output_setup_func()

void PLy_output_setup_func ( PLyObToDatum arg,
MemoryContext  arg_mcxt,
Oid  typeOid,
int32  typmod,
struct PLyProcedure proc 
)

Definition at line 295 of file plpy_typeio.c.

References PLyObToDatum::array, PLyObToTuple::atts, PLyObToDomain::base, check_stack_depth(), PLyObToDatum::domain, PLyObToDomain::domain_info, TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, PLyObToArray::elm, PLyObToArray::elmbasetype, fmgr_info_cxt(), FmgrInfo::fn_oid, PLyObToDatum::func, get_transform_tosql(), getBaseType(), getTypeInputInfo(), INVALID_TUPLEDESC_IDENTIFIER, InvalidOid, PLyProcedure::langid, lookup_type_cache(), PLyObToDatum::mcxt, MemoryContextAllocZero(), PLyObToTuple::natts, OidIsValid, PLy_output_setup_func(), PLyObject_ToBool(), PLyObject_ToBytea(), PLyObject_ToComposite(), PLyObject_ToDomain(), PLyObject_ToScalar(), PLyObject_ToTransform(), PLySequence_ToArray(), PLyObToTuple::recdesc, PLyObToTuple::recinfunc, PLyObToDatum::scalar, PLyObToDatum::transform, PLyProcedure::trftypes, PLyObToTuple::tupdescid, PLyObToDatum::tuple, TypeCacheEntry::typalign, PLyObToDatum::typalign, TypeCacheEntry::typbyval, PLyObToDatum::typbyval, TYPECACHE_DOMAIN_BASE_INFO, TypeCacheEntry::typelem, PLyObToTuple::typentry, PLyObToScalar::typfunc, PLyObToScalar::typioparam, TypeCacheEntry::typlen, PLyObToDatum::typlen, PLyObToDatum::typmod, PLyObToDatum::typoid, PLyObToTransform::typtransform, TypeCacheEntry::typtype, and PLyObToDatum::u.

Referenced by PLy_exec_trigger(), PLy_output_setup_func(), PLy_output_setup_tuple(), PLy_procedure_create(), and PLy_spi_prepare().

298 {
299  TypeCacheEntry *typentry;
300  char typtype;
301  Oid trfuncid;
302  Oid typinput;
303 
304  /* Since this is recursive, it could theoretically be driven to overflow */
306 
307  arg->typoid = typeOid;
308  arg->typmod = typmod;
309  arg->mcxt = arg_mcxt;
310 
311  /*
312  * Fetch typcache entry for the target type, asking for whatever info
313  * we'll need later. RECORD is a special case: just treat it as composite
314  * without bothering with the typcache entry.
315  */
316  if (typeOid != RECORDOID)
317  {
318  typentry = lookup_type_cache(typeOid, TYPECACHE_DOMAIN_BASE_INFO);
319  typtype = typentry->typtype;
320  arg->typbyval = typentry->typbyval;
321  arg->typlen = typentry->typlen;
322  arg->typalign = typentry->typalign;
323  }
324  else
325  {
326  typentry = NULL;
327  typtype = TYPTYPE_COMPOSITE;
328  /* hard-wired knowledge about type RECORD: */
329  arg->typbyval = false;
330  arg->typlen = -1;
331  arg->typalign = 'd';
332  }
333 
334  /*
335  * Choose conversion method. Note that transform functions are checked
336  * for composite and scalar types, but not for arrays or domains. This is
337  * somewhat historical, but we'd have a problem allowing them on domains,
338  * since we drill down through all levels of a domain nest without looking
339  * at the intermediate levels at all.
340  */
341  if (typtype == TYPTYPE_DOMAIN)
342  {
343  /* Domain */
344  arg->func = PLyObject_ToDomain;
345  arg->u.domain.domain_info = NULL;
346  /* Recursively set up conversion info for the element type */
347  arg->u.domain.base = (PLyObToDatum *)
348  MemoryContextAllocZero(arg_mcxt, sizeof(PLyObToDatum));
349  PLy_output_setup_func(arg->u.domain.base, arg_mcxt,
350  typentry->domainBaseType,
351  typentry->domainBaseTypmod,
352  proc);
353  }
354  else if (typentry &&
355  OidIsValid(typentry->typelem) && typentry->typlen == -1)
356  {
357  /* Standard varlena array (cf. get_element_type) */
358  arg->func = PLySequence_ToArray;
359  /* Get base type OID to insert into constructed array */
360  /* (note this might not be the same as the immediate child type) */
361  arg->u.array.elmbasetype = getBaseType(typentry->typelem);
362  /* Recursively set up conversion info for the element type */
363  arg->u.array.elm = (PLyObToDatum *)
364  MemoryContextAllocZero(arg_mcxt, sizeof(PLyObToDatum));
365  PLy_output_setup_func(arg->u.array.elm, arg_mcxt,
366  typentry->typelem, typmod,
367  proc);
368  }
369  else if ((trfuncid = get_transform_tosql(typeOid,
370  proc->langid,
371  proc->trftypes)))
372  {
374  fmgr_info_cxt(trfuncid, &arg->u.transform.typtransform, arg_mcxt);
375  }
376  else if (typtype == TYPTYPE_COMPOSITE)
377  {
378  /* Named composite type, or RECORD */
380  /* We'll set up the per-field data later */
381  arg->u.tuple.recdesc = NULL;
382  arg->u.tuple.typentry = typentry;
384  arg->u.tuple.atts = NULL;
385  arg->u.tuple.natts = 0;
386  /* Mark this invalid till needed, too */
388  }
389  else
390  {
391  /* Scalar type, but we have a couple of special cases */
392  switch (typeOid)
393  {
394  case BOOLOID:
395  arg->func = PLyObject_ToBool;
396  break;
397  case BYTEAOID:
398  arg->func = PLyObject_ToBytea;
399  break;
400  default:
401  arg->func = PLyObject_ToScalar;
402  getTypeInputInfo(typeOid, &typinput, &arg->u.scalar.typioparam);
403  fmgr_info_cxt(typinput, &arg->u.scalar.typfunc, arg_mcxt);
404  break;
405  }
406  }
407 }
void * domain_info
Definition: plpy_typeio.h:122
FmgrInfo typfunc
Definition: plpy_typeio.h:95
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
#define OidIsValid(objectId)
Definition: c.h:645
bool typbyval
Definition: typcache.h:38
PLyObToTransform transform
Definition: plpy_typeio.h:145
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:146
PLyObToDatum * base
Definition: plpy_typeio.h:121
PLyObToDatumFunc func
Definition: plpy_typeio.h:132
PLyObToDomain domain
Definition: plpy_typeio.h:144
Oid domainBaseType
Definition: typcache.h:105
static Datum PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1081
PLyObToArray array
Definition: plpy_typeio.h:142
TupleDesc recdesc
Definition: plpy_typeio.h:108
uint64 tupdescid
Definition: plpy_typeio.h:111
PLyObToScalar scalar
Definition: plpy_typeio.h:141
void check_stack_depth(void)
Definition: postgres.c:3284
static Datum PLyObject_ToDomain(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1106
static Datum PLyObject_ToBool(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:878
int32 domainBaseTypmod
Definition: typcache.h:106
FmgrInfo typtransform
Definition: plpy_typeio.h:127
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2641
static Datum PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:940
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:140
TypeCacheEntry * typentry
Definition: plpy_typeio.h:110
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:322
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
char typtype
Definition: typcache.h:41
PLyObToDatum * elm
Definition: plpy_typeio.h:101
MemoryContext mcxt
Definition: plpy_typeio.h:138
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1921
static Datum PLyObject_ToTransform(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1123
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:295
PLyObToTuple tuple
Definition: plpy_typeio.h:143
char typalign
Definition: typcache.h:39
static Datum PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1140
PLyObToDatum * atts
Definition: plpy_typeio.h:113
static Datum PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:896
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2299
FmgrInfo recinfunc
Definition: plpy_typeio.h:116
union PLyObToDatum::@166 u

◆ PLy_output_setup_record()

void PLy_output_setup_record ( PLyObToDatum arg,
TupleDesc  desc,
struct PLyProcedure proc 
)

Definition at line 260 of file plpy_typeio.c.

References Assert, BlessTupleDesc(), PLy_output_setup_tuple(), PLyObToTuple::recdesc, TupleDescData::tdtypeid, TupleDescData::tdtypmod, PLyObToDatum::tuple, PLyObToDatum::typmod, PLyObToDatum::typoid, and PLyObToDatum::u.

Referenced by PLy_function_build_args().

261 {
262  /* Makes no sense unless RECORD */
263  Assert(arg->typoid == RECORDOID);
264  Assert(desc->tdtypeid == RECORDOID);
265 
266  /*
267  * Bless the record type if not already done. We'd have to do this anyway
268  * to return a tuple, so we might as well force the issue so we can use
269  * the known-record-type code path.
270  */
271  BlessTupleDesc(desc);
272 
273  /*
274  * Update arg->typmod, and clear the recdesc link if it's changed. The
275  * next call of PLyObject_ToComposite will look up a long-lived tupdesc
276  * for the record type.
277  */
278  arg->typmod = desc->tdtypmod;
279  if (arg->u.tuple.recdesc &&
280  arg->u.tuple.recdesc->tdtypmod != arg->typmod)
281  arg->u.tuple.recdesc = NULL;
282 
283  /* Update derived data if necessary */
284  PLy_output_setup_tuple(arg, desc, proc);
285 }
TupleDesc recdesc
Definition: plpy_typeio.h:108
int32 tdtypmod
Definition: tupdesc.h:83
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2052
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:214
#define Assert(condition)
Definition: c.h:739
Oid tdtypeid
Definition: tupdesc.h:82
PLyObToTuple tuple
Definition: plpy_typeio.h:143
union PLyObToDatum::@166 u

◆ PLy_output_setup_tuple()

void PLy_output_setup_tuple ( PLyObToDatum arg,
TupleDesc  desc,
struct PLyProcedure proc 
)

Definition at line 214 of file plpy_typeio.c.

References Assert, PLyObToTuple::atts, PLyObToDatum::func, i, PLyObToDatum::mcxt, MemoryContextAllocZero(), TupleDescData::natts, PLyObToTuple::natts, pfree(), PLy_output_setup_func(), PLyObject_ToComposite(), PLyObToTuple::recdesc, PLyObToDatum::tuple, TupleDescAttr, PLyObToDatum::typmod, PLyObToDatum::typoid, and PLyObToDatum::u.

Referenced by PLy_exec_trigger(), PLy_output_setup_record(), and PLyObject_ToComposite().

215 {
216  int i;
217 
218  /* We should be working on a previously-set-up struct */
220 
221  /* Save pointer to tupdesc, but only if this is an anonymous record type */
222  if (arg->typoid == RECORDOID && arg->typmod < 0)
223  arg->u.tuple.recdesc = desc;
224 
225  /* (Re)allocate atts array as needed */
226  if (arg->u.tuple.natts != desc->natts)
227  {
228  if (arg->u.tuple.atts)
229  pfree(arg->u.tuple.atts);
230  arg->u.tuple.natts = desc->natts;
231  arg->u.tuple.atts = (PLyObToDatum *)
233  desc->natts * sizeof(PLyObToDatum));
234  }
235 
236  /* Fill the atts entries, except for dropped columns */
237  for (i = 0; i < desc->natts; i++)
238  {
239  Form_pg_attribute attr = TupleDescAttr(desc, i);
240  PLyObToDatum *att = &arg->u.tuple.atts[i];
241 
242  if (attr->attisdropped)
243  continue;
244 
245  if (att->typoid == attr->atttypid && att->typmod == attr->atttypmod)
246  continue; /* already set up this entry */
247 
248  PLy_output_setup_func(att, arg->mcxt,
249  attr->atttypid, attr->atttypmod,
250  proc);
251  }
252 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
PLyObToDatumFunc func
Definition: plpy_typeio.h:132
void pfree(void *pointer)
Definition: mcxt.c:1056
TupleDesc recdesc
Definition: plpy_typeio.h:108
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
static Datum PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:940
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
#define Assert(condition)
Definition: c.h:739
MemoryContext mcxt
Definition: plpy_typeio.h:138
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:295
PLyObToTuple tuple
Definition: plpy_typeio.h:143
int i
PLyObToDatum * atts
Definition: plpy_typeio.h:113
union PLyObToDatum::@166 u

◆ PLyObject_AsString()

char* PLyObject_AsString ( PyObject *  plrv)

Definition at line 1023 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_ToScalar(), and PLyString_ToComposite().

1024 {
1025  PyObject *plrv_bo;
1026  char *plrv_sc;
1027  size_t plen;
1028  size_t slen;
1029 
1030  if (PyUnicode_Check(plrv))
1031  plrv_bo = PLyUnicode_Bytes(plrv);
1032  else if (PyFloat_Check(plrv))
1033  {
1034  /* use repr() for floats, str() is lossy */
1035 #if PY_MAJOR_VERSION >= 3
1036  PyObject *s = PyObject_Repr(plrv);
1037 
1038  plrv_bo = PLyUnicode_Bytes(s);
1039  Py_XDECREF(s);
1040 #else
1041  plrv_bo = PyObject_Repr(plrv);
1042 #endif
1043  }
1044  else
1045  {
1046 #if PY_MAJOR_VERSION >= 3
1047  PyObject *s = PyObject_Str(plrv);
1048 
1049  plrv_bo = PLyUnicode_Bytes(s);
1050  Py_XDECREF(s);
1051 #else
1052  plrv_bo = PyObject_Str(plrv);
1053 #endif
1054  }
1055  if (!plrv_bo)
1056  PLy_elog(ERROR, "could not create string representation of Python object");
1057 
1058  plrv_sc = pstrdup(PyBytes_AsString(plrv_bo));
1059  plen = PyBytes_Size(plrv_bo);
1060  slen = strlen(plrv_sc);
1061 
1062  Py_XDECREF(plrv_bo);
1063 
1064  if (slen < plen)
1065  ereport(ERROR,
1066  (errcode(ERRCODE_DATATYPE_MISMATCH),
1067  errmsg("could not convert Python object into cstring: Python string representation appears to contain null bytes")));
1068  else if (slen > plen)
1069  elog(ERROR, "could not convert Python object into cstring: Python string longer than reported length");
1070  pg_verifymbstr(plrv_sc, slen, false);
1071 
1072  return plrv_sc;
1073 }
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:608
#define PyBytes_AsString
Definition: plpython.h:86
#define ERROR
Definition: elog.h:43
#define PLy_elog
#define ereport(elevel, rest)
Definition: elog.h:141
#define PyBytes_Size
Definition: plpython.h:88
PyObject * PLyUnicode_Bytes(PyObject *unicode)
Definition: plpy_util.c:21
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1914