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:135
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:403
PLyDatumToObFunc func
Definition: plpy_typeio.h:58
long val
Definition: informix.c:689
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
Definition: plpy_main.c:412

◆ 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:135
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:403
static PyObject * PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc)
Definition: plpy_typeio.c:820
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
Definition: plpy_main.c:412

◆ 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, BOOLOID, BYTEAOID, check_stack_depth(), TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, PLyArrayToOb::elm, FLOAT4OID, FLOAT8OID, fmgr_info_cxt(), PLyDatumToOb::func, get_transform_fromsql(), getTypeOutputInfo(), INT2OID, INT4OID, INT8OID, PLyProcedure::langid, lookup_type_cache(), PLyDatumToOb::mcxt, MemoryContextAllocZero(), PLyTupleToOb::natts, NUMERICOID, OidIsValid, OIDOID, 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, RECORDOID, PLyDatumToOb::scalar, PLyDatumToOb::transform, PLyProcedure::trftypes, PLyTupleToOb::tupdescseq, TypeCacheEntry::tupDescSeqNo, 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, TYPTYPE_COMPOSITE, TYPTYPE_DOMAIN, 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;
502  arg->u.tuple.tupdescseq = typentry ? typentry->tupDescSeqNo - 1 : 0;
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 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1872
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c: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:2646
FmgrInfo typfunc
Definition: plpy_typeio.h:31
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:553
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
#define OIDOID
Definition: pg_type.h:328
#define NUMERICOID
Definition: pg_type.h:554
#define INT4OID
Definition: pg_type.h:316
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:576
bool typbyval
Definition: typcache.h:38
static PyObject * PLyString_FromScalar(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:649
FmgrInfo typtransform
Definition: plpy_typeio.h:53
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:786
Oid domainBaseType
Definition: typcache.h:101
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
#define INT2OID
Definition: pg_type.h:308
static PyObject * PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:561
int64 tupdescseq
Definition: plpy_typeio.h:45
static PyObject * PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:635
void check_stack_depth(void)
Definition: postgres.c:3150
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:102
int16 typlen
Definition: plpy_typeio.h:62
#define RECORDOID
Definition: pg_type.h:680
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
static PyObject * PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:573
PLyDatumToOb * elm
Definition: plpy_typeio.h:36
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:136
#define FLOAT4OID
Definition: pg_type.h:416
int64 tupDescSeqNo
Definition: typcache.h:83
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:311
#define INT8OID
Definition: pg_type.h:304
char typtype
Definition: typcache.h:41
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:674
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:629
union PLyDatumToOb::@141 u
#define FLOAT8OID
Definition: pg_type.h:419
PLyScalarToOb scalar
Definition: plpy_typeio.h:67
#define BOOLOID
Definition: pg_type.h:288
#define BYTEAOID
Definition: pg_type.h:292
static PyObject * PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:662
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, RECORDOID, 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:90
int natts
Definition: tupdesc.h:79
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:786
void pfree(void *pointer)
Definition: mcxt.c:949
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:187
#define RECORDOID
Definition: pg_type.h:680
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
#define Assert(condition)
Definition: c.h:670
union PLyDatumToOb::@141 u
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, BOOLOID, BYTEAOID, 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(), 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, RECORDOID, PLyObToDatum::scalar, PLyObToDatum::transform, PLyProcedure::trftypes, PLyObToTuple::tupdescseq, TypeCacheEntry::tupDescSeqNo, 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, TYPTYPE_COMPOSITE, TYPTYPE_DOMAIN, 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;
387  arg->u.tuple.tupdescseq = typentry ? typentry->tupDescSeqNo - 1 : 0;
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 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
void * domain_info
Definition: plpy_typeio.h:121
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
FmgrInfo typfunc
Definition: plpy_typeio.h:94
int64 tupdescseq
Definition: plpy_typeio.h:110
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:37
#define OidIsValid(objectId)
Definition: c.h:576
bool typbyval
Definition: typcache.h:38
PLyObToTransform transform
Definition: plpy_typeio.h:144
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:101
static Datum PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1083
PLyObToArray array
Definition: plpy_typeio.h:141
TupleDesc recdesc
Definition: plpy_typeio.h:107
PLyObToScalar scalar
Definition: plpy_typeio.h:140
void check_stack_depth(void)
Definition: postgres.c:3150
static Datum PLyObject_ToDomain(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1108
static Datum PLyObject_ToBool(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:877
int32 domainBaseTypmod
Definition: typcache.h:102
FmgrInfo typtransform
Definition: plpy_typeio.h:126
#define RECORDOID
Definition: pg_type.h:680
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2613
static Datum PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:942
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:136
TypeCacheEntry * typentry
Definition: plpy_typeio.h:109
int64 tupDescSeqNo
Definition: typcache.h:83
union PLyObToDatum::@142 u
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:311
#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
#define BOOLOID
Definition: pg_type.h:288
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1893
static Datum PLyObject_ToTransform(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1125
#define BYTEAOID
Definition: pg_type.h:292
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:1142
PLyObToDatum * atts
Definition: plpy_typeio.h:112
static Datum PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:895
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2271
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, RECORDOID, 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:80
int32 tdtypmod
Definition: tupdesc.h:81
TupleDesc recdesc
Definition: plpy_typeio.h:107
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
#define RECORDOID
Definition: pg_type.h:680
union PLyObToDatum::@142 u
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:218
#define Assert(condition)
Definition: c.h:670
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, RECORDOID, 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:90
int natts
Definition: tupdesc.h:79
PLyObToDatumFunc func
Definition: plpy_typeio.h:131
void pfree(void *pointer)
Definition: mcxt.c:949
TupleDesc recdesc
Definition: plpy_typeio.h:107
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define RECORDOID
Definition: pg_type.h:680
static Datum PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:942
union PLyObToDatum::@142 u
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
#define Assert(condition)
Definition: c.h:670
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 1025 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().

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