PostgreSQL Source Code  git master
plpy_typeio.h File Reference
#include "access/htup.h"
#include "fmgr.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)
 
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

◆ PLyDatumToOb

Definition at line 25 of file plpy_typeio.h.

◆ PLyDatumToObFunc

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

Definition at line 27 of file plpy_typeio.h.

◆ PLyObToArray

◆ PLyObToDatum

Definition at line 86 of file plpy_typeio.h.

◆ PLyObToDatumFunc

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

Definition at line 88 of file plpy_typeio.h.

◆ PLyObToDomain

◆ PLyObToScalar

◆ PLyObToTransform

◆ PLyObToTuple

◆ PLyScalarToOb

◆ PLyTransformToOb

◆ PLyTupleToOb

Function Documentation

◆ PLy_input_convert()

PyObject* PLy_input_convert ( PLyDatumToOb arg,
Datum  val 
)

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

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

◆ PLy_input_from_tuple()

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

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

138 {
139  PyObject *dict;
141  MemoryContext scratch_context = PLy_get_scratch_context(exec_ctx);
142  MemoryContext oldcontext;
143 
144  /*
145  * As in PLy_input_convert, do the work in the scratch context.
146  */
147  MemoryContextReset(scratch_context);
148 
149  oldcontext = MemoryContextSwitchTo(scratch_context);
150 
151  dict = PLyDict_FromTuple(arg, tuple, desc);
152 
153  MemoryContextSwitchTo(oldcontext);
154 
155  return dict;
156 }
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:414
static PyObject * PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc)
Definition: plpy_typeio.c:818
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
Definition: plpy_main.c:423

◆ PLy_input_setup_func()

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

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

424 {
425  TypeCacheEntry *typentry;
426  char typtype;
427  Oid trfuncid;
428  Oid typoutput;
429  bool typisvarlena;
430 
431  /* Since this is recursive, it could theoretically be driven to overflow */
433 
434  arg->typoid = typeOid;
435  arg->typmod = typmod;
436  arg->mcxt = arg_mcxt;
437 
438  /*
439  * Fetch typcache entry for the target type, asking for whatever info
440  * we'll need later. RECORD is a special case: just treat it as composite
441  * without bothering with the typcache entry.
442  */
443  if (typeOid != RECORDOID)
444  {
445  typentry = lookup_type_cache(typeOid, TYPECACHE_DOMAIN_BASE_INFO);
446  typtype = typentry->typtype;
447  arg->typbyval = typentry->typbyval;
448  arg->typlen = typentry->typlen;
449  arg->typalign = typentry->typalign;
450  }
451  else
452  {
453  typentry = NULL;
454  typtype = TYPTYPE_COMPOSITE;
455  /* hard-wired knowledge about type RECORD: */
456  arg->typbyval = false;
457  arg->typlen = -1;
458  arg->typalign = 'd';
459  }
460 
461  /*
462  * Choose conversion method. Note that transform functions are checked
463  * for composite and scalar types, but not for arrays or domains. This is
464  * somewhat historical, but we'd have a problem allowing them on domains,
465  * since we drill down through all levels of a domain nest without looking
466  * at the intermediate levels at all.
467  */
468  if (typtype == TYPTYPE_DOMAIN)
469  {
470  /* Domain --- we don't care, just recurse down to the base type */
471  PLy_input_setup_func(arg, arg_mcxt,
472  typentry->domainBaseType,
473  typentry->domainBaseTypmod,
474  proc);
475  }
476  else if (typentry &&
477  OidIsValid(typentry->typelem) && typentry->typlen == -1)
478  {
479  /* Standard varlena array (cf. get_element_type) */
480  arg->func = PLyList_FromArray;
481  /* Recursively set up conversion info for the element type */
482  arg->u.array.elm = (PLyDatumToOb *)
483  MemoryContextAllocZero(arg_mcxt, sizeof(PLyDatumToOb));
484  PLy_input_setup_func(arg->u.array.elm, arg_mcxt,
485  typentry->typelem, typmod,
486  proc);
487  }
488  else if ((trfuncid = get_transform_fromsql(typeOid,
489  proc->langid,
490  proc->trftypes)))
491  {
493  fmgr_info_cxt(trfuncid, &arg->u.transform.typtransform, arg_mcxt);
494  }
495  else if (typtype == TYPTYPE_COMPOSITE)
496  {
497  /* Named composite type, or RECORD */
499  /* We'll set up the per-field data later */
500  arg->u.tuple.recdesc = NULL;
501  arg->u.tuple.typentry = typentry;
503  arg->u.tuple.atts = NULL;
504  arg->u.tuple.natts = 0;
505  }
506  else
507  {
508  /* Scalar type, but we have a couple of special cases */
509  switch (typeOid)
510  {
511  case BOOLOID:
512  arg->func = PLyBool_FromBool;
513  break;
514  case FLOAT4OID:
515  arg->func = PLyFloat_FromFloat4;
516  break;
517  case FLOAT8OID:
518  arg->func = PLyFloat_FromFloat8;
519  break;
520  case NUMERICOID:
522  break;
523  case INT2OID:
524  arg->func = PLyInt_FromInt16;
525  break;
526  case INT4OID:
527  arg->func = PLyInt_FromInt32;
528  break;
529  case INT8OID:
530  arg->func = PLyLong_FromInt64;
531  break;
532  case OIDOID:
533  arg->func = PLyLong_FromOid;
534  break;
535  case BYTEAOID:
536  arg->func = PLyBytes_FromBytea;
537  break;
538  default:
539  arg->func = PLyString_FromScalar;
540  getTypeOutputInfo(typeOid, &typoutput, &typisvarlena);
541  fmgr_info_cxt(typoutput, &arg->u.scalar.typfunc, arg_mcxt);
542  break;
543  }
544  }
545 }
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1876
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:619
TupleDesc recdesc
Definition: plpy_typeio.h:42
static PyObject * PLyInt_FromInt32(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:613
PLyDatumToOb * atts
Definition: plpy_typeio.h:47
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2650
FmgrInfo typfunc
Definition: plpy_typeio.h:31
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:553
uint64 tupdescid
Definition: plpy_typeio.h:45
union PLyDatumToOb::@151 u
TypeCacheEntry * typentry
Definition: plpy_typeio.h:44
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
#define OidIsValid(objectId)
Definition: c.h:605
bool typbyval
Definition: typcache.h:38
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:145
static PyObject * PLyString_FromScalar(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:645
FmgrInfo typtransform
Definition: plpy_typeio.h:53
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:784
Oid domainBaseType
Definition: typcache.h:104
static PyObject * PLyInt_FromInt16(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:607
PLyArrayToOb array
Definition: plpy_typeio.h:68
static PyObject * PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:567
PLyDatumToObFunc func
Definition: plpy_typeio.h:58
PLyTransformToOb transform
Definition: plpy_typeio.h:70
static PyObject * PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:561
static PyObject * PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:631
void check_stack_depth(void)
Definition: postgres.c:3159
int32 typmod
Definition: plpy_typeio.h:60
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:421
int32 domainBaseTypmod
Definition: typcache.h:105
int16 typlen
Definition: plpy_typeio.h:62
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:573
PLyDatumToOb * elm
Definition: plpy_typeio.h:36
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:139
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:814
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:321
char typtype
Definition: typcache.h:41
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:670
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:625
PLyScalarToOb scalar
Definition: plpy_typeio.h:67
static PyObject * PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:658
char typalign
Definition: typcache.h:39
MemoryContext mcxt
Definition: plpy_typeio.h:64
PLyTupleToOb tuple
Definition: plpy_typeio.h:69

◆ PLy_input_setup_tuple()

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

Definition at line 168 of file plpy_typeio.c.

References Assert, PLyTupleToOb::atts, PLyDatumToOb::func, i, PLyDatumToOb::mcxt, MemoryContextAllocZero(), PLyTupleToOb::natts, tupleDesc::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().

169 {
170  int i;
171 
172  /* We should be working on a previously-set-up struct */
174 
175  /* Save pointer to tupdesc, but only if this is an anonymous record type */
176  if (arg->typoid == RECORDOID && arg->typmod < 0)
177  arg->u.tuple.recdesc = desc;
178 
179  /* (Re)allocate atts array as needed */
180  if (arg->u.tuple.natts != desc->natts)
181  {
182  if (arg->u.tuple.atts)
183  pfree(arg->u.tuple.atts);
184  arg->u.tuple.natts = desc->natts;
185  arg->u.tuple.atts = (PLyDatumToOb *)
187  desc->natts * sizeof(PLyDatumToOb));
188  }
189 
190  /* Fill the atts entries, except for dropped columns */
191  for (i = 0; i < desc->natts; i++)
192  {
193  Form_pg_attribute attr = TupleDescAttr(desc, i);
194  PLyDatumToOb *att = &arg->u.tuple.atts[i];
195 
196  if (attr->attisdropped)
197  continue;
198 
199  if (att->typoid == attr->atttypid && att->typmod == attr->atttypmod)
200  continue; /* already set up this entry */
201 
202  PLy_input_setup_func(att, arg->mcxt,
203  attr->atttypid, attr->atttypmod,
204  proc);
205  }
206 }
TupleDesc recdesc
Definition: plpy_typeio.h:42
PLyDatumToOb * atts
Definition: plpy_typeio.h:47
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
union PLyDatumToOb::@151 u
int natts
Definition: tupdesc.h:82
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:784
void pfree(void *pointer)
Definition: mcxt.c:1031
PLyDatumToObFunc func
Definition: plpy_typeio.h:58
int32 typmod
Definition: plpy_typeio.h:60
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:421
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:814
#define Assert(condition)
Definition: c.h:699
int i
MemoryContext mcxt
Definition: plpy_typeio.h:64
PLyTupleToOb tuple
Definition: plpy_typeio.h:69

◆ PLy_output_convert()

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

Definition at line 123 of file plpy_typeio.c.

References PLyObToDatum::func.

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

124 {
125  /* at outer level, we are not considering an array element */
126  return arg->func(arg, val, isnull, false);
127 }
PLyObToDatumFunc func
Definition: plpy_typeio.h:131
long val
Definition: informix.c:689

◆ PLy_output_setup_func()

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

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

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

◆ PLy_output_setup_record()

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

Definition at line 264 of file plpy_typeio.c.

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

Referenced by PLy_function_build_args().

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

◆ PLy_output_setup_tuple()

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

Definition at line 218 of file plpy_typeio.c.

References Assert, PLyObToTuple::atts, PLyObToDatum::func, i, PLyObToDatum::mcxt, MemoryContextAllocZero(), tupleDesc::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().

219 {
220  int i;
221 
222  /* We should be working on a previously-set-up struct */
224 
225  /* Save pointer to tupdesc, but only if this is an anonymous record type */
226  if (arg->typoid == RECORDOID && arg->typmod < 0)
227  arg->u.tuple.recdesc = desc;
228 
229  /* (Re)allocate atts array as needed */
230  if (arg->u.tuple.natts != desc->natts)
231  {
232  if (arg->u.tuple.atts)
233  pfree(arg->u.tuple.atts);
234  arg->u.tuple.natts = desc->natts;
235  arg->u.tuple.atts = (PLyObToDatum *)
237  desc->natts * sizeof(PLyObToDatum));
238  }
239 
240  /* Fill the atts entries, except for dropped columns */
241  for (i = 0; i < desc->natts; i++)
242  {
243  Form_pg_attribute attr = TupleDescAttr(desc, i);
244  PLyObToDatum *att = &arg->u.tuple.atts[i];
245 
246  if (attr->attisdropped)
247  continue;
248 
249  if (att->typoid == attr->atttypid && att->typmod == attr->atttypmod)
250  continue; /* already set up this entry */
251 
252  PLy_output_setup_func(att, arg->mcxt,
253  attr->atttypid, attr->atttypmod,
254  proc);
255  }
256 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
int natts
Definition: tupdesc.h:82
PLyObToDatumFunc func
Definition: plpy_typeio.h:131
void pfree(void *pointer)
Definition: mcxt.c:1031
TupleDesc recdesc
Definition: plpy_typeio.h:107
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
union PLyObToDatum::@152 u
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:814
#define Assert(condition)
Definition: c.h:699
MemoryContext mcxt
Definition: plpy_typeio.h:137
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:299
PLyObToTuple tuple
Definition: plpy_typeio.h:142
int i
PLyObToDatum * atts
Definition: plpy_typeio.h:112

◆ 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:1161
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PyBytes_AsString
Definition: plpython.h:84
#define ERROR
Definition: elog.h:43
#define PLy_elog
#define ereport(elevel, rest)
Definition: elog.h:122
#define PyBytes_Size
Definition: plpython.h:86
PyObject * PLyUnicode_Bytes(PyObject *unicode)
Definition: plpy_util.c:25
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