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

Go to the source code of this file.

Data Structures

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

Typedefs

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

Functions

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

Typedef Documentation

◆ PLyArrayToOb

typedef struct PLyArrayToOb PLyArrayToOb

◆ PLyDatumToOb

typedef struct PLyDatumToOb PLyDatumToOb

Definition at line 1 of file plpy_typeio.h.

◆ PLyDatumToObFunc

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

Definition at line 28 of file plpy_typeio.h.

◆ PLyObToArray

typedef struct PLyObToArray PLyObToArray

◆ PLyObToDatum

typedef struct PLyObToDatum PLyObToDatum

Definition at line 28 of file plpy_typeio.h.

◆ PLyObToDatumFunc

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

Definition at line 89 of file plpy_typeio.h.

◆ PLyObToDomain

typedef struct PLyObToDomain PLyObToDomain

◆ PLyObToScalar

typedef struct PLyObToScalar PLyObToScalar

◆ PLyObToTransform

◆ PLyObToTuple

typedef struct PLyObToTuple PLyObToTuple

◆ PLyScalarToOb

typedef struct PLyScalarToOb PLyScalarToOb

◆ PLyTransformToOb

◆ PLyTupleToOb

typedef struct PLyTupleToOb PLyTupleToOb

Function Documentation

◆ PLy_input_convert()

PyObject* PLy_input_convert ( PLyDatumToOb arg,
Datum  val 
)

Definition at line 80 of file plpy_typeio.c.

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

References arg, MemoryContextReset(), MemoryContextSwitchTo(), PLy_current_execution_context(), PLy_get_scratch_context(), and val.

Referenced by PLy_function_build_args().

◆ PLy_input_from_tuple()

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

Definition at line 133 of file plpy_typeio.c.

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

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

◆ PLy_input_setup_func()

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

Definition at line 417 of file plpy_typeio.c.

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

References arg, check_stack_depth(), TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, fmgr_info_cxt(), get_transform_fromsql(), getTypeOutputInfo(), INVALID_TUPLEDESC_IDENTIFIER, PLyProcedure::langid, lookup_type_cache(), MemoryContextAllocZero(), PLyBool_FromBool(), PLyBytes_FromBytea(), PLyDecimal_FromNumeric(), PLyDict_FromComposite(), PLyFloat_FromFloat4(), PLyFloat_FromFloat8(), PLyList_FromArray(), PLyLong_FromInt16(), PLyLong_FromInt32(), PLyLong_FromInt64(), PLyLong_FromOid(), PLyObject_FromTransform(), PLyUnicode_FromScalar(), PLyProcedure::trftypes, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TYPECACHE_DOMAIN_BASE_INFO, TypeCacheEntry::typelem, TypeCacheEntry::typlen, and TypeCacheEntry::typtype.

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

◆ PLy_input_setup_tuple()

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

Definition at line 164 of file plpy_typeio.c.

165 {
166  int i;
167 
168  /* We should be working on a previously-set-up struct */
169  Assert(arg->func == PLyDict_FromComposite);
170 
171  /* Save pointer to tupdesc, but only if this is an anonymous record type */
172  if (arg->typoid == RECORDOID && arg->typmod < 0)
173  arg->u.tuple.recdesc = desc;
174 
175  /* (Re)allocate atts array as needed */
176  if (arg->u.tuple.natts != desc->natts)
177  {
178  if (arg->u.tuple.atts)
179  pfree(arg->u.tuple.atts);
180  arg->u.tuple.natts = desc->natts;
181  arg->u.tuple.atts = (PLyDatumToOb *)
183  desc->natts * sizeof(PLyDatumToOb));
184  }
185 
186  /* Fill the atts entries, except for dropped columns */
187  for (i = 0; i < desc->natts; i++)
188  {
189  Form_pg_attribute attr = TupleDescAttr(desc, i);
190  PLyDatumToOb *att = &arg->u.tuple.atts[i];
191 
192  if (attr->attisdropped)
193  continue;
194 
195  if (att->typoid == attr->atttypid && att->typmod == attr->atttypmod)
196  continue; /* already set up this entry */
197 
198  PLy_input_setup_func(att, arg->mcxt,
199  attr->atttypid, attr->atttypmod,
200  proc);
201  }
202 }
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1175
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
int32 typmod
Definition: plpy_typeio.h:61
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References arg, Assert(), i, MemoryContextAllocZero(), TupleDescData::natts, pfree(), PLy_input_setup_func(), PLyDict_FromComposite(), TupleDescAttr, PLyDatumToOb::typmod, and PLyDatumToOb::typoid.

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

◆ PLy_output_convert()

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

Definition at line 119 of file plpy_typeio.c.

120 {
121  /* at outer level, we are not considering an array element */
122  return arg->func(arg, val, isnull, false);
123 }

References arg, and val.

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

◆ PLy_output_setup_func()

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

Definition at line 295 of file plpy_typeio.c.

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

References arg, check_stack_depth(), TypeCacheEntry::domainBaseType, TypeCacheEntry::domainBaseTypmod, fmgr_info_cxt(), get_transform_tosql(), getBaseType(), getTypeInputInfo(), INVALID_TUPLEDESC_IDENTIFIER, InvalidOid, PLyProcedure::langid, lookup_type_cache(), MemoryContextAllocZero(), PLyObject_ToBool(), PLyObject_ToBytea(), PLyObject_ToComposite(), PLyObject_ToDomain(), PLyObject_ToScalar(), PLyObject_ToTransform(), PLySequence_ToArray(), PLyProcedure::trftypes, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TYPECACHE_DOMAIN_BASE_INFO, TypeCacheEntry::typelem, TypeCacheEntry::typlen, and TypeCacheEntry::typtype.

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

◆ PLy_output_setup_record()

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

Definition at line 260 of file plpy_typeio.c.

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

References arg, Assert(), BlessTupleDesc(), PLy_output_setup_tuple(), TupleDescData::tdtypeid, and TupleDescData::tdtypmod.

Referenced by PLy_function_build_args().

◆ PLy_output_setup_tuple()

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

Definition at line 214 of file plpy_typeio.c.

215 {
216  int i;
217 
218  /* We should be working on a previously-set-up struct */
219  Assert(arg->func == PLyObject_ToComposite);
220 
221  /* Save pointer to tupdesc, but only if this is an anonymous record type */
222  if (arg->typoid == RECORDOID && arg->typmod < 0)
223  arg->u.tuple.recdesc = desc;
224 
225  /* (Re)allocate atts array as needed */
226  if (arg->u.tuple.natts != desc->natts)
227  {
228  if (arg->u.tuple.atts)
229  pfree(arg->u.tuple.atts);
230  arg->u.tuple.natts = desc->natts;
231  arg->u.tuple.atts = (PLyObToDatum *)
233  desc->natts * sizeof(PLyObToDatum));
234  }
235 
236  /* Fill the atts entries, except for dropped columns */
237  for (i = 0; i < desc->natts; i++)
238  {
239  Form_pg_attribute attr = TupleDescAttr(desc, i);
240  PLyObToDatum *att = &arg->u.tuple.atts[i];
241 
242  if (attr->attisdropped)
243  continue;
244 
245  if (att->typoid == attr->atttypid && att->typmod == attr->atttypmod)
246  continue; /* already set up this entry */
247 
248  PLy_output_setup_func(att, arg->mcxt,
249  attr->atttypid, attr->atttypmod,
250  proc);
251  }
252 }

References arg, Assert(), i, MemoryContextAllocZero(), TupleDescData::natts, pfree(), PLy_output_setup_func(), PLyObject_ToComposite(), TupleDescAttr, PLyObToDatum::typmod, and PLyObToDatum::typoid.

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

◆ PLyObject_AsString()

char* PLyObject_AsString ( PyObject *  plrv)

Definition at line 1023 of file plpy_typeio.c.

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  PyObject *s = PyObject_Repr(plrv);
1036 
1037  plrv_bo = PLyUnicode_Bytes(s);
1038  Py_XDECREF(s);
1039  }
1040  else
1041  {
1042  PyObject *s = PyObject_Str(plrv);
1043 
1044  plrv_bo = PLyUnicode_Bytes(s);
1045  Py_XDECREF(s);
1046  }
1047  if (!plrv_bo)
1048  PLy_elog(ERROR, "could not create string representation of Python object");
1049 
1050  plrv_sc = pstrdup(PyBytes_AsString(plrv_bo));
1051  plen = PyBytes_Size(plrv_bo);
1052  slen = strlen(plrv_sc);
1053 
1054  Py_XDECREF(plrv_bo);
1055 
1056  if (slen < plen)
1057  ereport(ERROR,
1058  (errcode(ERRCODE_DATATYPE_MISMATCH),
1059  errmsg("could not convert Python object into cstring: Python string representation appears to contain null bytes")));
1060  else if (slen > plen)
1061  elog(ERROR, "could not convert Python object into cstring: Python string longer than reported length");
1062  pg_verifymbstr(plrv_sc, slen, false);
1063 
1064  return plrv_sc;
1065 }
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
#define PLy_elog
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1505
char * pstrdup(const char *in)
Definition: mcxt.c:1305
PyObject * PLyUnicode_Bytes(PyObject *unicode)
Definition: plpy_util.c:21

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

Referenced by PLyObject_ToScalar(), and PLyUnicode_ToComposite().