PostgreSQL Source Code  git master
plpy_typeio.h File Reference
#include "access/htup.h"
#include "fmgr.h"
#include "utils/typcache.h"
#include "plpython.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 27 of file plpy_typeio.h.

◆ PLyDatumToObFunc

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

Definition at line 29 of file plpy_typeio.h.

◆ PLyObToArray

typedef struct PLyObToArray PLyObToArray

◆ PLyObToDatum

typedef struct PLyObToDatum PLyObToDatum

Definition at line 88 of file plpy_typeio.h.

◆ PLyObToDatumFunc

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

Definition at line 90 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 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:60
long val
Definition: informix.c:684
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,
bool  include_generated 
)

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, include_generated);
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, bool include_generated)
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:1900
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:619
TupleDesc recdesc
Definition: plpy_typeio.h:44
static PyObject * PLyInt_FromInt32(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:613
PLyDatumToOb * atts
Definition: plpy_typeio.h:49
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2674
FmgrInfo typfunc
Definition: plpy_typeio.h:33
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:553
uint64 tupdescid
Definition: plpy_typeio.h:47
TypeCacheEntry * typentry
Definition: plpy_typeio.h:46
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
#define OidIsValid(objectId)
Definition: c.h:638
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:645
FmgrInfo typtransform
Definition: plpy_typeio.h:55
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:784
Oid domainBaseType
Definition: typcache.h:105
static PyObject * PLyInt_FromInt16(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:607
PLyArrayToOb array
Definition: plpy_typeio.h:70
static PyObject * PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:567
PLyDatumToObFunc func
Definition: plpy_typeio.h:60
PLyTransformToOb transform
Definition: plpy_typeio.h:72
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:3262
int32 typmod
Definition: plpy_typeio.h:62
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:106
int16 typlen
Definition: plpy_typeio.h:64
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:38
#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:670
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:625
PLyScalarToOb scalar
Definition: plpy_typeio.h:69
static PyObject * PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:658
char typalign
Definition: typcache.h:39
union PLyDatumToOb::@165 u
MemoryContext mcxt
Definition: plpy_typeio.h:66
PLyTupleToOb tuple
Definition: plpy_typeio.h:71

◆ 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, 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().

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:44
PLyDatumToOb * atts
Definition: plpy_typeio.h:49
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:784
void pfree(void *pointer)
Definition: mcxt.c:1056
PLyDatumToObFunc func
Definition: plpy_typeio.h:60
int32 typmod
Definition: plpy_typeio.h:62
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:200
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
#define Assert(condition)
Definition: c.h:732
int i
union PLyDatumToOb::@165 u
MemoryContext mcxt
Definition: plpy_typeio.h:66
PLyTupleToOb tuple
Definition: plpy_typeio.h:71

◆ 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:133
long val
Definition: informix.c:684

◆ 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:123
FmgrInfo typfunc
Definition: plpy_typeio.h:96
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
#define OidIsValid(objectId)
Definition: c.h:638
bool typbyval
Definition: typcache.h:38
PLyObToTransform transform
Definition: plpy_typeio.h:146
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:146
PLyObToDatum * base
Definition: plpy_typeio.h:122
PLyObToDatumFunc func
Definition: plpy_typeio.h:133
PLyObToDomain domain
Definition: plpy_typeio.h:145
Oid domainBaseType
Definition: typcache.h:105
static Datum PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1088
PLyObToArray array
Definition: plpy_typeio.h:143
TupleDesc recdesc
Definition: plpy_typeio.h:109
uint64 tupdescid
Definition: plpy_typeio.h:112
PLyObToScalar scalar
Definition: plpy_typeio.h:142
void check_stack_depth(void)
Definition: postgres.c:3262
static Datum PLyObject_ToDomain(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1113
static Datum PLyObject_ToBool(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:882
int32 domainBaseTypmod
Definition: typcache.h:106
FmgrInfo typtransform
Definition: plpy_typeio.h:128
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:947
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:140
TypeCacheEntry * typentry
Definition: plpy_typeio.h:111
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:102
MemoryContext mcxt
Definition: plpy_typeio.h:139
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:1130
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:144
char typalign
Definition: typcache.h:39
static Datum PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1147
PLyObToDatum * atts
Definition: plpy_typeio.h:114
static Datum PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:900
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2299
FmgrInfo recinfunc
Definition: plpy_typeio.h:117
union PLyObToDatum::@166 u

◆ 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, TupleDescData::tdtypeid, TupleDescData::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 }
TupleDesc recdesc
Definition: plpy_typeio.h:109
int32 tdtypmod
Definition: tupdesc.h:83
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2048
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:218
#define Assert(condition)
Definition: c.h:732
Oid tdtypeid
Definition: tupdesc.h:82
PLyObToTuple tuple
Definition: plpy_typeio.h:144
union PLyObToDatum::@166 u

◆ 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(), 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().

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:92
PLyObToDatumFunc func
Definition: plpy_typeio.h:133
void pfree(void *pointer)
Definition: mcxt.c:1056
TupleDesc recdesc
Definition: plpy_typeio.h:109
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:947
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
#define Assert(condition)
Definition: c.h:732
MemoryContext mcxt
Definition: plpy_typeio.h:139
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:144
int i
PLyObToDatum * atts
Definition: plpy_typeio.h:114
union PLyObToDatum::@166 u

◆ PLyObject_AsString()

char* PLyObject_AsString ( PyObject *  plrv)

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

1031 {
1032  PyObject *plrv_bo;
1033  char *plrv_sc;
1034  size_t plen;
1035  size_t slen;
1036 
1037  if (PyUnicode_Check(plrv))
1038  plrv_bo = PLyUnicode_Bytes(plrv);
1039  else if (PyFloat_Check(plrv))
1040  {
1041  /* use repr() for floats, str() is lossy */
1042 #if PY_MAJOR_VERSION >= 3
1043  PyObject *s = PyObject_Repr(plrv);
1044 
1045  plrv_bo = PLyUnicode_Bytes(s);
1046  Py_XDECREF(s);
1047 #else
1048  plrv_bo = PyObject_Repr(plrv);
1049 #endif
1050  }
1051  else
1052  {
1053 #if PY_MAJOR_VERSION >= 3
1054  PyObject *s = PyObject_Str(plrv);
1055 
1056  plrv_bo = PLyUnicode_Bytes(s);
1057  Py_XDECREF(s);
1058 #else
1059  plrv_bo = PyObject_Str(plrv);
1060 #endif
1061  }
1062  if (!plrv_bo)
1063  PLy_elog(ERROR, "could not create string representation of Python object");
1064 
1065  plrv_sc = pstrdup(PyBytes_AsString(plrv_bo));
1066  plen = PyBytes_Size(plrv_bo);
1067  slen = strlen(plrv_sc);
1068 
1069  Py_XDECREF(plrv_bo);
1070 
1071  if (slen < plen)
1072  ereport(ERROR,
1073  (errcode(ERRCODE_DATATYPE_MISMATCH),
1074  errmsg("could not convert Python object into cstring: Python string representation appears to contain null bytes")));
1075  else if (slen > plen)
1076  elog(ERROR, "could not convert Python object into cstring: Python string longer than reported length");
1077  pg_verifymbstr(plrv_sc, slen, false);
1078 
1079  return plrv_sc;
1080 }
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:570
#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:25
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1914