PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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

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

Typedef Documentation

◆ PLyArrayToOb

typedef struct PLyArrayToOb PLyArrayToOb

◆ PLyDatumToOb

typedef struct PLyDatumToOb PLyDatumToOb

Definition at line 26 of file plpy_typeio.h.

◆ PLyDatumToObFunc

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

Definition at line 28 of file plpy_typeio.h.

◆ PLyObToArray

typedef struct PLyObToArray PLyObToArray

◆ PLyObToDatum

typedef struct PLyObToDatum PLyObToDatum

Definition at line 87 of file plpy_typeio.h.

◆ PLyObToDatumFunc

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

Definition at line 89 of file plpy_typeio.h.

◆ PLyObToDomain

typedef struct PLyObToDomain PLyObToDomain

◆ PLyObToScalar

typedef struct PLyObToScalar PLyObToScalar

◆ PLyObToTransform

◆ PLyObToTuple

typedef struct PLyObToTuple PLyObToTuple

◆ PLyScalarToOb

typedef struct PLyScalarToOb PLyScalarToOb

◆ PLyTransformToOb

◆ PLyTupleToOb

typedef struct PLyTupleToOb PLyTupleToOb

Function Documentation

◆ PLy_input_convert()

PGDLLEXPORT PyObject * PLy_input_convert ( PLyDatumToOb arg,
Datum  val 
)

Definition at line 81 of file plpy_typeio.c.

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

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

Referenced by PLy_function_build_args().

◆ PLy_input_from_tuple()

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

Definition at line 134 of file plpy_typeio.c.

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

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()

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

Definition at line 418 of file plpy_typeio.c.

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

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(), PLy_input_setup_func(), 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_func(), PLy_input_setup_tuple(), PLy_procedure_create(), and PLy_spi_execute_fetch_result().

◆ PLy_input_setup_tuple()

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

Definition at line 165 of file plpy_typeio.c.

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

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()

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

Definition at line 120 of file plpy_typeio.c.

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

References arg, and val.

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

◆ PLy_output_setup_func()

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

Definition at line 296 of file plpy_typeio.c.

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

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(), PLy_output_setup_func(), 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_func(), PLy_output_setup_tuple(), PLy_procedure_create(), and PLy_spi_prepare().

◆ PLy_output_setup_record()

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

Definition at line 261 of file plpy_typeio.c.

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

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

Referenced by PLy_exec_function().

◆ PLy_output_setup_tuple()

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

Definition at line 215 of file plpy_typeio.c.

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

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()

PGDLLEXPORT char * PLyObject_AsString ( PyObject *  plrv)

Definition at line 1024 of file plpy_typeio.c.

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

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

Referenced by PLyObject_ToScalar(), and PLyUnicode_ToComposite().