PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plpy_typeio.c
Go to the documentation of this file.
1 /*
2  * transforming Datums to Python objects and vice versa
3  *
4  * src/pl/plpython/plpy_typeio.c
5  */
6 
7 #include "postgres.h"
8 
9 #include "access/htup_details.h"
10 #include "access/transam.h"
11 #include "catalog/pg_type.h"
12 #include "funcapi.h"
13 #include "mb/pg_wchar.h"
14 #include "parser/parse_type.h"
15 #include "utils/array.h"
16 #include "utils/builtins.h"
17 #include "utils/fmgroids.h"
18 #include "utils/lsyscache.h"
19 #include "utils/memutils.h"
20 #include "utils/numeric.h"
21 #include "utils/syscache.h"
22 #include "utils/typcache.h"
23 
24 #include "plpython.h"
25 
26 #include "plpy_typeio.h"
27 
28 #include "plpy_elog.h"
29 #include "plpy_main.h"
30 
31 
32 /* I/O function caching */
33 static void PLy_input_datum_func2(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes);
34 static void PLy_output_datum_func2(PLyObToDatum *arg, MemoryContext arg_mcxt, HeapTuple typeTup, Oid langid, List *trftypes);
35 
36 /* conversion from Datums to Python objects */
37 static PyObject *PLyBool_FromBool(PLyDatumToOb *arg, Datum d);
38 static PyObject *PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d);
39 static PyObject *PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d);
40 static PyObject *PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d);
41 static PyObject *PLyInt_FromInt16(PLyDatumToOb *arg, Datum d);
42 static PyObject *PLyInt_FromInt32(PLyDatumToOb *arg, Datum d);
43 static PyObject *PLyLong_FromInt64(PLyDatumToOb *arg, Datum d);
44 static PyObject *PLyLong_FromOid(PLyDatumToOb *arg, Datum d);
45 static PyObject *PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d);
46 static PyObject *PLyString_FromDatum(PLyDatumToOb *arg, Datum d);
47 static PyObject *PLyObject_FromTransform(PLyDatumToOb *arg, Datum d);
48 static PyObject *PLyList_FromArray(PLyDatumToOb *arg, Datum d);
49 static PyObject *PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
50  char **dataptr_p, bits8 **bitmap_p, int *bitmask_p);
51 
52 /* conversion from Python objects to Datums */
53 static Datum PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray);
54 static Datum PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray);
55 static Datum PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray);
56 static Datum PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray);
57 static Datum PLyObject_ToTransform(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray);
58 static Datum PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray);
59 static void PLySequence_ToArray_recurse(PLyObToDatum *elm, PyObject *list,
60  int *dims, int ndim, int dim,
61  Datum *elems, bool *nulls, int *currelem);
62 
63 /* conversion from Python objects to composite Datums (used by triggers and SRFs) */
64 static Datum PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string, bool inarray);
65 static Datum PLyMapping_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *mapping);
66 static Datum PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence);
67 static Datum PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object, bool inarray);
68 
69 void
71 {
72  arg->is_rowtype = -1;
73  arg->in.r.natts = arg->out.r.natts = 0;
74  arg->in.r.atts = NULL;
75  arg->out.r.atts = NULL;
76  arg->typ_relid = InvalidOid;
79  arg->mcxt = mcxt;
80 }
81 
82 /*
83  * Conversion functions. Remember output from Python is input to
84  * PostgreSQL, and vice versa.
85  */
86 void
87 PLy_input_datum_func(PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
88 {
89  if (arg->is_rowtype > 0)
90  elog(ERROR, "PLyTypeInfo struct is initialized for Tuple");
91  arg->is_rowtype = 0;
92  PLy_input_datum_func2(&(arg->in.d), arg->mcxt, typeOid, typeTup, langid, trftypes);
93 }
94 
95 void
96 PLy_output_datum_func(PLyTypeInfo *arg, HeapTuple typeTup, Oid langid, List *trftypes)
97 {
98  if (arg->is_rowtype > 0)
99  elog(ERROR, "PLyTypeInfo struct is initialized for a Tuple");
100  arg->is_rowtype = 0;
101  PLy_output_datum_func2(&(arg->out.d), arg->mcxt, typeTup, langid, trftypes);
102 }
103 
104 void
106 {
107  int i;
109  MemoryContext oldcxt;
110 
111  oldcxt = MemoryContextSwitchTo(arg->mcxt);
112 
113  if (arg->is_rowtype == 0)
114  elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
115  arg->is_rowtype = 1;
116 
117  if (arg->in.r.natts != desc->natts)
118  {
119  if (arg->in.r.atts)
120  pfree(arg->in.r.atts);
121  arg->in.r.natts = desc->natts;
122  arg->in.r.atts = palloc0(desc->natts * sizeof(PLyDatumToOb));
123  }
124 
125  /* Can this be an unnamed tuple? If not, then an Assert would be enough */
126  if (desc->tdtypmod != -1)
127  elog(ERROR, "received unnamed record type as input");
128 
129  Assert(OidIsValid(desc->tdtypeid));
130 
131  /*
132  * RECORDOID means we got called to create input functions for a tuple
133  * fetched by plpy.execute or for an anonymous record type
134  */
135  if (desc->tdtypeid != RECORDOID)
136  {
137  HeapTuple relTup;
138 
139  /* Get the pg_class tuple corresponding to the type of the input */
140  arg->typ_relid = typeidTypeRelid(desc->tdtypeid);
142  if (!HeapTupleIsValid(relTup))
143  elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);
144 
145  /* Remember XMIN and TID for later validation if cache is still OK */
147  arg->typrel_tid = relTup->t_self;
148 
149  ReleaseSysCache(relTup);
150  }
151 
152  for (i = 0; i < desc->natts; i++)
153  {
154  HeapTuple typeTup;
155 
156  if (desc->attrs[i]->attisdropped)
157  continue;
158 
159  if (arg->in.r.atts[i].typoid == desc->attrs[i]->atttypid)
160  continue; /* already set up this entry */
161 
162  typeTup = SearchSysCache1(TYPEOID,
163  ObjectIdGetDatum(desc->attrs[i]->atttypid));
164  if (!HeapTupleIsValid(typeTup))
165  elog(ERROR, "cache lookup failed for type %u",
166  desc->attrs[i]->atttypid);
167 
168  PLy_input_datum_func2(&(arg->in.r.atts[i]), arg->mcxt,
169  desc->attrs[i]->atttypid,
170  typeTup,
171  exec_ctx->curr_proc->langid,
172  exec_ctx->curr_proc->trftypes);
173 
174  ReleaseSysCache(typeTup);
175  }
176 
177  MemoryContextSwitchTo(oldcxt);
178 }
179 
180 void
182 {
183  int i;
185  MemoryContext oldcxt;
186 
187  oldcxt = MemoryContextSwitchTo(arg->mcxt);
188 
189  if (arg->is_rowtype == 0)
190  elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
191  arg->is_rowtype = 1;
192 
193  if (arg->out.r.natts != desc->natts)
194  {
195  if (arg->out.r.atts)
196  pfree(arg->out.r.atts);
197  arg->out.r.natts = desc->natts;
198  arg->out.r.atts = palloc0(desc->natts * sizeof(PLyObToDatum));
199  }
200 
201  Assert(OidIsValid(desc->tdtypeid));
202 
203  /*
204  * RECORDOID means we got called to create output functions for an
205  * anonymous record type
206  */
207  if (desc->tdtypeid != RECORDOID)
208  {
209  HeapTuple relTup;
210 
211  /* Get the pg_class tuple corresponding to the type of the output */
212  arg->typ_relid = typeidTypeRelid(desc->tdtypeid);
214  if (!HeapTupleIsValid(relTup))
215  elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);
216 
217  /* Remember XMIN and TID for later validation if cache is still OK */
219  arg->typrel_tid = relTup->t_self;
220 
221  ReleaseSysCache(relTup);
222  }
223 
224  for (i = 0; i < desc->natts; i++)
225  {
226  HeapTuple typeTup;
227 
228  if (desc->attrs[i]->attisdropped)
229  continue;
230 
231  if (arg->out.r.atts[i].typoid == desc->attrs[i]->atttypid)
232  continue; /* already set up this entry */
233 
234  typeTup = SearchSysCache1(TYPEOID,
235  ObjectIdGetDatum(desc->attrs[i]->atttypid));
236  if (!HeapTupleIsValid(typeTup))
237  elog(ERROR, "cache lookup failed for type %u",
238  desc->attrs[i]->atttypid);
239 
240  PLy_output_datum_func2(&(arg->out.r.atts[i]), arg->mcxt, typeTup,
241  exec_ctx->curr_proc->langid,
242  exec_ctx->curr_proc->trftypes);
243 
244  ReleaseSysCache(typeTup);
245  }
246 
247  MemoryContextSwitchTo(oldcxt);
248 }
249 
250 void
252 {
253  /*
254  * If the output record functions are already set, we just have to check
255  * if the record descriptor has not changed
256  */
257  if ((arg->is_rowtype == 1) &&
258  (arg->out.d.typmod != -1) &&
259  (arg->out.d.typmod == desc->tdtypmod))
260  return;
261 
262  /* bless the record to make it known to the typcache lookup code */
263  BlessTupleDesc(desc);
264  /* save the freshly generated typmod */
265  arg->out.d.typmod = desc->tdtypmod;
266  /* proceed with normal I/O function caching */
267  PLy_output_tuple_funcs(arg, desc);
268 
269  /*
270  * it should change is_rowtype to 1, so we won't go through this again
271  * unless the output record description changes
272  */
273  Assert(arg->is_rowtype == 1);
274 }
275 
276 /*
277  * Transform a tuple into a Python dict object.
278  */
279 PyObject *
281 {
282  PyObject *volatile dict;
284  MemoryContext scratch_context = PLy_get_scratch_context(exec_ctx);
285  MemoryContext oldcontext = CurrentMemoryContext;
286 
287  if (info->is_rowtype != 1)
288  elog(ERROR, "PLyTypeInfo structure describes a datum");
289 
290  dict = PyDict_New();
291  if (dict == NULL)
292  PLy_elog(ERROR, "could not create new dictionary");
293 
294  PG_TRY();
295  {
296  int i;
297 
298  /*
299  * Do the work in the scratch context to avoid leaking memory from the
300  * datatype output function calls.
301  */
302  MemoryContextSwitchTo(scratch_context);
303  for (i = 0; i < info->in.r.natts; i++)
304  {
305  char *key;
306  Datum vattr;
307  bool is_null;
308  PyObject *value;
309 
310  if (desc->attrs[i]->attisdropped)
311  continue;
312 
313  key = NameStr(desc->attrs[i]->attname);
314  vattr = heap_getattr(tuple, (i + 1), desc, &is_null);
315 
316  if (is_null || info->in.r.atts[i].func == NULL)
317  PyDict_SetItemString(dict, key, Py_None);
318  else
319  {
320  value = (info->in.r.atts[i].func) (&info->in.r.atts[i], vattr);
321  PyDict_SetItemString(dict, key, value);
322  Py_DECREF(value);
323  }
324  }
325  MemoryContextSwitchTo(oldcontext);
326  MemoryContextReset(scratch_context);
327  }
328  PG_CATCH();
329  {
330  MemoryContextSwitchTo(oldcontext);
331  Py_DECREF(dict);
332  PG_RE_THROW();
333  }
334  PG_END_TRY();
335 
336  return dict;
337 }
338 
339 /*
340  * Convert a Python object to a composite Datum, using all supported
341  * conversion methods: composite as a string, as a sequence, as a mapping or
342  * as an object that has __getattr__ support.
343  */
344 Datum
345 PLyObject_ToCompositeDatum(PLyTypeInfo *info, TupleDesc desc, PyObject *plrv, bool inarray)
346 {
347  Datum datum;
348 
349  if (PyString_Check(plrv) || PyUnicode_Check(plrv))
350  datum = PLyString_ToComposite(info, desc, plrv, inarray);
351  else if (PySequence_Check(plrv))
352  /* composite type as sequence (tuple, list etc) */
353  datum = PLySequence_ToComposite(info, desc, plrv);
354  else if (PyMapping_Check(plrv))
355  /* composite type as mapping (currently only dict) */
356  datum = PLyMapping_ToComposite(info, desc, plrv);
357  else
358  /* returned as smth, must provide method __getattr__(name) */
359  datum = PLyGenericObject_ToComposite(info, desc, plrv, inarray);
360 
361  return datum;
362 }
363 
364 static void
365 PLy_output_datum_func2(PLyObToDatum *arg, MemoryContext arg_mcxt, HeapTuple typeTup, Oid langid, List *trftypes)
366 {
367  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
368  Oid element_type;
369  Oid base_type;
370  Oid funcid;
371  MemoryContext oldcxt;
372 
373  oldcxt = MemoryContextSwitchTo(arg_mcxt);
374 
375  fmgr_info_cxt(typeStruct->typinput, &arg->typfunc, arg_mcxt);
376  arg->typoid = HeapTupleGetOid(typeTup);
377  arg->typmod = -1;
378  arg->typioparam = getTypeIOParam(typeTup);
379  arg->typbyval = typeStruct->typbyval;
380 
381  element_type = get_base_element_type(arg->typoid);
382  base_type = getBaseType(element_type ? element_type : arg->typoid);
383 
384  /*
385  * Select a conversion function to convert Python objects to PostgreSQL
386  * datums.
387  */
388 
389  if ((funcid = get_transform_tosql(base_type, langid, trftypes)))
390  {
392  fmgr_info_cxt(funcid, &arg->typtransform, arg_mcxt);
393  }
394  else if (typeStruct->typtype == TYPTYPE_COMPOSITE)
395  {
397  }
398  else
399  switch (base_type)
400  {
401  case BOOLOID:
402  arg->func = PLyObject_ToBool;
403  break;
404  case BYTEAOID:
405  arg->func = PLyObject_ToBytea;
406  break;
407  default:
408  arg->func = PLyObject_ToDatum;
409  break;
410  }
411 
412  if (element_type)
413  {
414  char dummy_delim;
415  Oid funcid;
416 
417  if (type_is_rowtype(element_type))
419 
420  arg->elm = palloc0(sizeof(*arg->elm));
421  arg->elm->func = arg->func;
422  arg->elm->typtransform = arg->typtransform;
423  arg->func = PLySequence_ToArray;
424 
425  arg->elm->typoid = element_type;
426  arg->elm->typmod = -1;
427  get_type_io_data(element_type, IOFunc_input,
428  &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
429  &arg->elm->typioparam, &funcid);
430  fmgr_info_cxt(funcid, &arg->elm->typfunc, arg_mcxt);
431  }
432 
433  MemoryContextSwitchTo(oldcxt);
434 }
435 
436 static void
437 PLy_input_datum_func2(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
438 {
439  Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
440  Oid element_type;
441  Oid base_type;
442  Oid funcid;
443  MemoryContext oldcxt;
444 
445  oldcxt = MemoryContextSwitchTo(arg_mcxt);
446 
447  /* Get the type's conversion information */
448  fmgr_info_cxt(typeStruct->typoutput, &arg->typfunc, arg_mcxt);
449  arg->typoid = HeapTupleGetOid(typeTup);
450  arg->typmod = -1;
451  arg->typioparam = getTypeIOParam(typeTup);
452  arg->typbyval = typeStruct->typbyval;
453  arg->typlen = typeStruct->typlen;
454  arg->typalign = typeStruct->typalign;
455 
456  /* Determine which kind of Python object we will convert to */
457 
458  element_type = get_base_element_type(typeOid);
459  base_type = getBaseType(element_type ? element_type : typeOid);
460 
461  if ((funcid = get_transform_fromsql(base_type, langid, trftypes)))
462  {
464  fmgr_info_cxt(funcid, &arg->typtransform, arg_mcxt);
465  }
466  else
467  switch (base_type)
468  {
469  case BOOLOID:
470  arg->func = PLyBool_FromBool;
471  break;
472  case FLOAT4OID:
473  arg->func = PLyFloat_FromFloat4;
474  break;
475  case FLOAT8OID:
476  arg->func = PLyFloat_FromFloat8;
477  break;
478  case NUMERICOID:
480  break;
481  case INT2OID:
482  arg->func = PLyInt_FromInt16;
483  break;
484  case INT4OID:
485  arg->func = PLyInt_FromInt32;
486  break;
487  case INT8OID:
488  arg->func = PLyLong_FromInt64;
489  break;
490  case OIDOID:
491  arg->func = PLyLong_FromOid;
492  break;
493  case BYTEAOID:
494  arg->func = PLyBytes_FromBytea;
495  break;
496  default:
497  arg->func = PLyString_FromDatum;
498  break;
499  }
500 
501  if (element_type)
502  {
503  char dummy_delim;
504  Oid funcid;
505 
506  arg->elm = palloc0(sizeof(*arg->elm));
507  arg->elm->func = arg->func;
508  arg->elm->typtransform = arg->typtransform;
509  arg->func = PLyList_FromArray;
510  arg->elm->typoid = element_type;
511  arg->elm->typmod = -1;
512  get_type_io_data(element_type, IOFunc_output,
513  &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
514  &arg->elm->typioparam, &funcid);
515  fmgr_info_cxt(funcid, &arg->elm->typfunc, arg_mcxt);
516  }
517 
518  MemoryContextSwitchTo(oldcxt);
519 }
520 
521 static PyObject *
523 {
524  if (DatumGetBool(d))
525  Py_RETURN_TRUE;
526  Py_RETURN_FALSE;
527 }
528 
529 static PyObject *
531 {
532  return PyFloat_FromDouble(DatumGetFloat4(d));
533 }
534 
535 static PyObject *
537 {
538  return PyFloat_FromDouble(DatumGetFloat8(d));
539 }
540 
541 static PyObject *
543 {
544  static PyObject *decimal_constructor;
545  char *str;
546  PyObject *pyvalue;
547 
548  /* Try to import cdecimal. If it doesn't exist, fall back to decimal. */
549  if (!decimal_constructor)
550  {
551  PyObject *decimal_module;
552 
553  decimal_module = PyImport_ImportModule("cdecimal");
554  if (!decimal_module)
555  {
556  PyErr_Clear();
557  decimal_module = PyImport_ImportModule("decimal");
558  }
559  if (!decimal_module)
560  PLy_elog(ERROR, "could not import a module for Decimal constructor");
561 
562  decimal_constructor = PyObject_GetAttrString(decimal_module, "Decimal");
563  if (!decimal_constructor)
564  PLy_elog(ERROR, "no Decimal attribute in module");
565  }
566 
568  pyvalue = PyObject_CallFunction(decimal_constructor, "s", str);
569  if (!pyvalue)
570  PLy_elog(ERROR, "conversion from numeric to Decimal failed");
571 
572  return pyvalue;
573 }
574 
575 static PyObject *
577 {
578  return PyInt_FromLong(DatumGetInt16(d));
579 }
580 
581 static PyObject *
583 {
584  return PyInt_FromLong(DatumGetInt32(d));
585 }
586 
587 static PyObject *
589 {
590  /* on 32 bit platforms "long" may be too small */
591  if (sizeof(int64) > sizeof(long))
592  return PyLong_FromLongLong(DatumGetInt64(d));
593  else
594  return PyLong_FromLong(DatumGetInt64(d));
595 }
596 
597 static PyObject *
599 {
600  return PyLong_FromUnsignedLong(DatumGetObjectId(d));
601 }
602 
603 static PyObject *
605 {
606  text *txt = DatumGetByteaPP(d);
607  char *str = VARDATA_ANY(txt);
608  size_t size = VARSIZE_ANY_EXHDR(txt);
609 
610  return PyBytes_FromStringAndSize(str, size);
611 }
612 
613 static PyObject *
615 {
616  char *x = OutputFunctionCall(&arg->typfunc, d);
617  PyObject *r = PyString_FromString(x);
618 
619  pfree(x);
620  return r;
621 }
622 
623 static PyObject *
625 {
626  return (PyObject *) DatumGetPointer(FunctionCall1(&arg->typtransform, d));
627 }
628 
629 static PyObject *
631 {
632  ArrayType *array = DatumGetArrayTypeP(d);
633  PLyDatumToOb *elm = arg->elm;
634  int ndim;
635  int *dims;
636  char *dataptr;
637  bits8 *bitmap;
638  int bitmask;
639 
640  if (ARR_NDIM(array) == 0)
641  return PyList_New(0);
642 
643  /* Array dimensions and left bounds */
644  ndim = ARR_NDIM(array);
645  dims = ARR_DIMS(array);
646  Assert(ndim < MAXDIM);
647 
648  /*
649  * We iterate the SQL array in the physical order it's stored in the
650  * datum. For example, for a 3-dimensional array the order of iteration
651  * would be the following: [0,0,0] elements through [0,0,k], then [0,1,0]
652  * through [0,1,k] till [0,m,k], then [1,0,0] through [1,0,k] till
653  * [1,m,k], and so on.
654  *
655  * In Python, there are no multi-dimensional lists as such, but they are
656  * represented as a list of lists. So a 3-d array of [n,m,k] elements is a
657  * list of n m-element arrays, each element of which is k-element array.
658  * PLyList_FromArray_recurse() builds the Python list for a single
659  * dimension, and recurses for the next inner dimension.
660  */
661  dataptr = ARR_DATA_PTR(array);
662  bitmap = ARR_NULLBITMAP(array);
663  bitmask = 1;
664 
665  return PLyList_FromArray_recurse(elm, dims, ndim, 0,
666  &dataptr, &bitmap, &bitmask);
667 }
668 
669 static PyObject *
670 PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
671  char **dataptr_p, bits8 **bitmap_p, int *bitmask_p)
672 {
673  int i;
674  PyObject *list;
675 
676  list = PyList_New(dims[dim]);
677 
678  if (dim < ndim - 1)
679  {
680  /* Outer dimension. Recurse for each inner slice. */
681  for (i = 0; i < dims[dim]; i++)
682  {
683  PyObject *sublist;
684 
685  sublist = PLyList_FromArray_recurse(elm, dims, ndim, dim + 1,
686  dataptr_p, bitmap_p, bitmask_p);
687  PyList_SET_ITEM(list, i, sublist);
688  }
689  }
690  else
691  {
692  /*
693  * Innermost dimension. Fill the list with the values from the array
694  * for this slice.
695  */
696  char *dataptr = *dataptr_p;
697  bits8 *bitmap = *bitmap_p;
698  int bitmask = *bitmask_p;
699 
700  for (i = 0; i < dims[dim]; i++)
701  {
702  /* checking for NULL */
703  if (bitmap && (*bitmap & bitmask) == 0)
704  {
705  Py_INCREF(Py_None);
706  PyList_SET_ITEM(list, i, Py_None);
707  }
708  else
709  {
710  Datum itemvalue;
711 
712  itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen);
713  PyList_SET_ITEM(list, i, elm->func(elm, itemvalue));
714  dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr);
715  dataptr = (char *) att_align_nominal(dataptr, elm->typalign);
716  }
717 
718  /* advance bitmap pointer if any */
719  if (bitmap)
720  {
721  bitmask <<= 1;
722  if (bitmask == 0x100 /* (1<<8) */ )
723  {
724  bitmap++;
725  bitmask = 1;
726  }
727  }
728  }
729 
730  *dataptr_p = dataptr;
731  *bitmap_p = bitmap;
732  *bitmask_p = bitmask;
733  }
734 
735  return list;
736 }
737 
738 /*
739  * Convert a Python object to a PostgreSQL bool datum. This can't go
740  * through the generic conversion function, because Python attaches a
741  * Boolean value to everything, more things than the PostgreSQL bool
742  * type can parse.
743  */
744 static Datum
745 PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
746 {
747  Datum rv;
748 
749  Assert(plrv != Py_None);
750  rv = BoolGetDatum(PyObject_IsTrue(plrv));
751 
752  if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
753  domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
754 
755  return rv;
756 }
757 
758 /*
759  * Convert a Python object to a PostgreSQL bytea datum. This doesn't
760  * go through the generic conversion function to circumvent problems
761  * with embedded nulls. And it's faster this way.
762  */
763 static Datum
764 PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
765 {
766  PyObject *volatile plrv_so = NULL;
767  Datum rv;
768 
769  Assert(plrv != Py_None);
770 
771  plrv_so = PyObject_Bytes(plrv);
772  if (!plrv_so)
773  PLy_elog(ERROR, "could not create bytes representation of Python object");
774 
775  PG_TRY();
776  {
777  char *plrv_sc = PyBytes_AsString(plrv_so);
778  size_t len = PyBytes_Size(plrv_so);
779  size_t size = len + VARHDRSZ;
780  bytea *result = palloc(size);
781 
782  SET_VARSIZE(result, size);
783  memcpy(VARDATA(result), plrv_sc, len);
784  rv = PointerGetDatum(result);
785  }
786  PG_CATCH();
787  {
788  Py_XDECREF(plrv_so);
789  PG_RE_THROW();
790  }
791  PG_END_TRY();
792 
793  Py_XDECREF(plrv_so);
794 
795  if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
796  domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
797 
798  return rv;
799 }
800 
801 
802 /*
803  * Convert a Python object to a composite type. First look up the type's
804  * description, then route the Python object through the conversion function
805  * for obtaining PostgreSQL tuples.
806  */
807 static Datum
808 PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
809 {
810  Datum rv;
811  PLyTypeInfo info;
812  TupleDesc desc;
813  MemoryContext cxt;
814 
815  if (typmod != -1)
816  elog(ERROR, "received unnamed record type as input");
817 
818  /* Create a dummy PLyTypeInfo */
820  "PL/Python temp context",
822  MemSet(&info, 0, sizeof(PLyTypeInfo));
823  PLy_typeinfo_init(&info, cxt);
824  /* Mark it as needing output routines lookup */
825  info.is_rowtype = 2;
826 
827  desc = lookup_rowtype_tupdesc(arg->typoid, arg->typmod);
828 
829  /*
830  * This will set up the dummy PLyTypeInfo's output conversion routines,
831  * since we left is_rowtype as 2. A future optimization could be caching
832  * that info instead of looking it up every time a tuple is returned from
833  * the function.
834  */
835  rv = PLyObject_ToCompositeDatum(&info, desc, plrv, inarray);
836 
837  ReleaseTupleDesc(desc);
838 
839  MemoryContextDelete(cxt);
840 
841  return rv;
842 }
843 
844 
845 /*
846  * Convert Python object to C string in server encoding.
847  */
848 char *
849 PLyObject_AsString(PyObject *plrv)
850 {
851  PyObject *plrv_bo;
852  char *plrv_sc;
853  size_t plen;
854  size_t slen;
855 
856  if (PyUnicode_Check(plrv))
857  plrv_bo = PLyUnicode_Bytes(plrv);
858  else if (PyFloat_Check(plrv))
859  {
860  /* use repr() for floats, str() is lossy */
861 #if PY_MAJOR_VERSION >= 3
862  PyObject *s = PyObject_Repr(plrv);
863 
864  plrv_bo = PLyUnicode_Bytes(s);
865  Py_XDECREF(s);
866 #else
867  plrv_bo = PyObject_Repr(plrv);
868 #endif
869  }
870  else
871  {
872 #if PY_MAJOR_VERSION >= 3
873  PyObject *s = PyObject_Str(plrv);
874 
875  plrv_bo = PLyUnicode_Bytes(s);
876  Py_XDECREF(s);
877 #else
878  plrv_bo = PyObject_Str(plrv);
879 #endif
880  }
881  if (!plrv_bo)
882  PLy_elog(ERROR, "could not create string representation of Python object");
883 
884  plrv_sc = pstrdup(PyBytes_AsString(plrv_bo));
885  plen = PyBytes_Size(plrv_bo);
886  slen = strlen(plrv_sc);
887 
888  Py_XDECREF(plrv_bo);
889 
890  if (slen < plen)
891  ereport(ERROR,
892  (errcode(ERRCODE_DATATYPE_MISMATCH),
893  errmsg("could not convert Python object into cstring: Python string representation appears to contain null bytes")));
894  else if (slen > plen)
895  elog(ERROR, "could not convert Python object into cstring: Python string longer than reported length");
896  pg_verifymbstr(plrv_sc, slen, false);
897 
898  return plrv_sc;
899 }
900 
901 
902 /*
903  * Generic conversion function: Convert PyObject to cstring and
904  * cstring into PostgreSQL type.
905  */
906 static Datum
907 PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
908 {
909  char *str;
910 
911  Assert(plrv != Py_None);
912 
913  str = PLyObject_AsString(plrv);
914 
915  /*
916  * If we are parsing a composite type within an array, and the string
917  * isn't a valid record literal, there's a high chance that the function
918  * did something like:
919  *
920  * CREATE FUNCTION .. RETURNS comptype[] AS $$ return [['foo', 'bar']] $$
921  * LANGUAGE plpython;
922  *
923  * Before PostgreSQL 10, that was interpreted as a single-dimensional
924  * array, containing record ('foo', 'bar'). PostgreSQL 10 added support
925  * for multi-dimensional arrays, and it is now interpreted as a
926  * two-dimensional array, containing two records, 'foo', and 'bar'.
927  * record_in() will throw an error, because "foo" is not a valid record
928  * literal.
929  *
930  * To make that less confusing to users who are upgrading from older
931  * versions, try to give a hint in the typical instances of that. If we
932  * are parsing an array of composite types, and we see a string literal
933  * that is not a valid record literal, give a hint. We only want to give
934  * the hint in the narrow case of a malformed string literal, not any
935  * error from record_in(), so check for that case here specifically.
936  *
937  * This check better match the one in record_in(), so that we don't forbid
938  * literals that are actually valid!
939  */
940  if (inarray && arg->typfunc.fn_oid == F_RECORD_IN)
941  {
942  char *ptr = str;
943 
944  /* Allow leading whitespace */
945  while (*ptr && isspace((unsigned char) *ptr))
946  ptr++;
947  if (*ptr++ != '(')
948  ereport(ERROR,
949  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
950  errmsg("malformed record literal: \"%s\"", str),
951  errdetail("Missing left parenthesis."),
952  errhint("To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".")));
953  }
954 
955  return InputFunctionCall(&arg->typfunc,
956  str,
957  arg->typioparam,
958  typmod);
959 }
960 
961 
962 static Datum
963 PLyObject_ToTransform(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
964 {
965  return FunctionCall1(&arg->typtransform, PointerGetDatum(plrv));
966 }
967 
968 
969 static Datum
970 PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
971 {
972  ArrayType *array;
973  int i;
974  Datum *elems;
975  bool *nulls;
976  int64 len;
977  int ndim;
978  int dims[MAXDIM];
979  int lbs[MAXDIM];
980  int currelem;
981  Datum rv;
982  PyObject *pyptr = plrv;
983  PyObject *next;
984 
985  Assert(plrv != Py_None);
986 
987  /*
988  * Determine the number of dimensions, and their sizes.
989  */
990  ndim = 0;
991  len = 1;
992 
993  Py_INCREF(plrv);
994 
995  for (;;)
996  {
997  if (!PyList_Check(pyptr))
998  break;
999 
1000  if (ndim == MAXDIM)
1001  PLy_elog(ERROR, "number of array dimensions exceeds the maximum allowed (%d)", MAXDIM);
1002 
1003  dims[ndim] = PySequence_Length(pyptr);
1004  if (dims[ndim] < 0)
1005  PLy_elog(ERROR, "cannot determine sequence length for function return value");
1006 
1007  if (dims[ndim] > MaxAllocSize)
1008  PLy_elog(ERROR, "array size exceeds the maximum allowed");
1009 
1010  len *= dims[ndim];
1011  if (len > MaxAllocSize)
1012  PLy_elog(ERROR, "array size exceeds the maximum allowed");
1013 
1014  if (dims[ndim] == 0)
1015  {
1016  /* empty sequence */
1017  break;
1018  }
1019 
1020  ndim++;
1021 
1022  next = PySequence_GetItem(pyptr, 0);
1023  Py_XDECREF(pyptr);
1024  pyptr = next;
1025  }
1026  Py_XDECREF(pyptr);
1027 
1028  /*
1029  * Check for zero dimensions. This happens if the object is a tuple or a
1030  * string, rather than a list, or is not a sequence at all. We don't map
1031  * tuples or strings to arrays in general, but in the first level, be
1032  * lenient, for historical reasons. So if the object is a sequence of any
1033  * kind, treat it as a one-dimensional array.
1034  */
1035  if (ndim == 0)
1036  {
1037  if (!PySequence_Check(plrv))
1038  PLy_elog(ERROR, "return value of function with array return type is not a Python sequence");
1039 
1040  ndim = 1;
1041  len = dims[0] = PySequence_Length(plrv);
1042  }
1043 
1044  /*
1045  * Traverse the Python lists, in depth-first order, and collect all the
1046  * elements at the bottom level into 'elems'/'nulls' arrays.
1047  */
1048  elems = palloc(sizeof(Datum) * len);
1049  nulls = palloc(sizeof(bool) * len);
1050  currelem = 0;
1051  PLySequence_ToArray_recurse(arg->elm, plrv,
1052  dims, ndim, 0,
1053  elems, nulls, &currelem);
1054 
1055  for (i = 0; i < ndim; i++)
1056  lbs[i] = 1;
1057 
1058  array = construct_md_array(elems,
1059  nulls,
1060  ndim,
1061  dims,
1062  lbs,
1064  arg->elm->typlen,
1065  arg->elm->typbyval,
1066  arg->elm->typalign);
1067 
1068  /*
1069  * If the result type is a domain of array, the resulting array must be
1070  * checked.
1071  */
1072  rv = PointerGetDatum(array);
1073  if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
1074  domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
1075  return rv;
1076 }
1077 
1078 /*
1079  * Helper function for PLySequence_ToArray. Traverse a Python list of lists in
1080  * depth-first order, storing the elements in 'elems'.
1081  */
1082 static void
1084  int *dims, int ndim, int dim,
1085  Datum *elems, bool *nulls, int *currelem)
1086 {
1087  int i;
1088 
1089  if (PySequence_Length(list) != dims[dim])
1090  PLy_elog(ERROR,
1091  "multidimensional arrays must have array expressions with matching dimensions. "
1092  "PL/Python function return value has sequence length %d while expected %d",
1093  (int) PySequence_Length(list), dims[dim]);
1094 
1095  if (dim < ndim - 1)
1096  {
1097  for (i = 0; i < dims[dim]; i++)
1098  {
1099  PyObject *sublist = PySequence_GetItem(list, i);
1100 
1101  PLySequence_ToArray_recurse(elm, sublist, dims, ndim, dim + 1,
1102  elems, nulls, currelem);
1103  Py_XDECREF(sublist);
1104  }
1105  }
1106  else
1107  {
1108  for (i = 0; i < dims[dim]; i++)
1109  {
1110  PyObject *obj = PySequence_GetItem(list, i);
1111 
1112  if (obj == Py_None)
1113  {
1114  nulls[*currelem] = true;
1115  elems[*currelem] = (Datum) 0;
1116  }
1117  else
1118  {
1119  nulls[*currelem] = false;
1120  elems[*currelem] = elm->func(elm, -1, obj, true);
1121  }
1122  Py_XDECREF(obj);
1123  (*currelem)++;
1124  }
1125  }
1126 }
1127 
1128 
1129 static Datum
1130 PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string, bool inarray)
1131 {
1132  Datum result;
1133  HeapTuple typeTup;
1134  PLyTypeInfo locinfo;
1136  MemoryContext cxt;
1137 
1138  /* Create a dummy PLyTypeInfo */
1140  "PL/Python temp context",
1142  MemSet(&locinfo, 0, sizeof(PLyTypeInfo));
1143  PLy_typeinfo_init(&locinfo, cxt);
1144 
1145  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(desc->tdtypeid));
1146  if (!HeapTupleIsValid(typeTup))
1147  elog(ERROR, "cache lookup failed for type %u", desc->tdtypeid);
1148 
1149  PLy_output_datum_func2(&locinfo.out.d, locinfo.mcxt, typeTup,
1150  exec_ctx->curr_proc->langid,
1151  exec_ctx->curr_proc->trftypes);
1152 
1153  ReleaseSysCache(typeTup);
1154 
1155  result = PLyObject_ToDatum(&locinfo.out.d, desc->tdtypmod, string, inarray);
1156 
1157  MemoryContextDelete(cxt);
1158 
1159  return result;
1160 }
1161 
1162 
1163 static Datum
1164 PLyMapping_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *mapping)
1165 {
1166  Datum result;
1167  HeapTuple tuple;
1168  Datum *values;
1169  bool *nulls;
1170  volatile int i;
1171 
1172  Assert(PyMapping_Check(mapping));
1173 
1174  if (info->is_rowtype == 2)
1175  PLy_output_tuple_funcs(info, desc);
1176  Assert(info->is_rowtype == 1);
1177 
1178  /* Build tuple */
1179  values = palloc(sizeof(Datum) * desc->natts);
1180  nulls = palloc(sizeof(bool) * desc->natts);
1181  for (i = 0; i < desc->natts; ++i)
1182  {
1183  char *key;
1184  PyObject *volatile value;
1185  PLyObToDatum *att;
1186 
1187  if (desc->attrs[i]->attisdropped)
1188  {
1189  values[i] = (Datum) 0;
1190  nulls[i] = true;
1191  continue;
1192  }
1193 
1194  key = NameStr(desc->attrs[i]->attname);
1195  value = NULL;
1196  att = &info->out.r.atts[i];
1197  PG_TRY();
1198  {
1199  value = PyMapping_GetItemString(mapping, key);
1200  if (value == Py_None)
1201  {
1202  values[i] = (Datum) NULL;
1203  nulls[i] = true;
1204  }
1205  else if (value)
1206  {
1207  values[i] = (att->func) (att, -1, value, false);
1208  nulls[i] = false;
1209  }
1210  else
1211  ereport(ERROR,
1212  (errcode(ERRCODE_UNDEFINED_COLUMN),
1213  errmsg("key \"%s\" not found in mapping", key),
1214  errhint("To return null in a column, "
1215  "add the value None to the mapping with the key named after the column.")));
1216 
1217  Py_XDECREF(value);
1218  value = NULL;
1219  }
1220  PG_CATCH();
1221  {
1222  Py_XDECREF(value);
1223  PG_RE_THROW();
1224  }
1225  PG_END_TRY();
1226  }
1227 
1228  tuple = heap_form_tuple(desc, values, nulls);
1229  result = heap_copy_tuple_as_datum(tuple, desc);
1230  heap_freetuple(tuple);
1231 
1232  pfree(values);
1233  pfree(nulls);
1234 
1235  return result;
1236 }
1237 
1238 
1239 static Datum
1240 PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence)
1241 {
1242  Datum result;
1243  HeapTuple tuple;
1244  Datum *values;
1245  bool *nulls;
1246  volatile int idx;
1247  volatile int i;
1248 
1249  Assert(PySequence_Check(sequence));
1250 
1251  /*
1252  * Check that sequence length is exactly same as PG tuple's. We actually
1253  * can ignore exceeding items or assume missing ones as null but to avoid
1254  * plpython developer's errors we are strict here
1255  */
1256  idx = 0;
1257  for (i = 0; i < desc->natts; i++)
1258  {
1259  if (!desc->attrs[i]->attisdropped)
1260  idx++;
1261  }
1262  if (PySequence_Length(sequence) != idx)
1263  ereport(ERROR,
1264  (errcode(ERRCODE_DATATYPE_MISMATCH),
1265  errmsg("length of returned sequence did not match number of columns in row")));
1266 
1267  if (info->is_rowtype == 2)
1268  PLy_output_tuple_funcs(info, desc);
1269  Assert(info->is_rowtype == 1);
1270 
1271  /* Build tuple */
1272  values = palloc(sizeof(Datum) * desc->natts);
1273  nulls = palloc(sizeof(bool) * desc->natts);
1274  idx = 0;
1275  for (i = 0; i < desc->natts; ++i)
1276  {
1277  PyObject *volatile value;
1278  PLyObToDatum *att;
1279 
1280  if (desc->attrs[i]->attisdropped)
1281  {
1282  values[i] = (Datum) 0;
1283  nulls[i] = true;
1284  continue;
1285  }
1286 
1287  value = NULL;
1288  att = &info->out.r.atts[i];
1289  PG_TRY();
1290  {
1291  value = PySequence_GetItem(sequence, idx);
1292  Assert(value);
1293  if (value == Py_None)
1294  {
1295  values[i] = (Datum) NULL;
1296  nulls[i] = true;
1297  }
1298  else if (value)
1299  {
1300  values[i] = (att->func) (att, -1, value, false);
1301  nulls[i] = false;
1302  }
1303 
1304  Py_XDECREF(value);
1305  value = NULL;
1306  }
1307  PG_CATCH();
1308  {
1309  Py_XDECREF(value);
1310  PG_RE_THROW();
1311  }
1312  PG_END_TRY();
1313 
1314  idx++;
1315  }
1316 
1317  tuple = heap_form_tuple(desc, values, nulls);
1318  result = heap_copy_tuple_as_datum(tuple, desc);
1319  heap_freetuple(tuple);
1320 
1321  pfree(values);
1322  pfree(nulls);
1323 
1324  return result;
1325 }
1326 
1327 
1328 static Datum
1329 PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object, bool inarray)
1330 {
1331  Datum result;
1332  HeapTuple tuple;
1333  Datum *values;
1334  bool *nulls;
1335  volatile int i;
1336 
1337  if (info->is_rowtype == 2)
1338  PLy_output_tuple_funcs(info, desc);
1339  Assert(info->is_rowtype == 1);
1340 
1341  /* Build tuple */
1342  values = palloc(sizeof(Datum) * desc->natts);
1343  nulls = palloc(sizeof(bool) * desc->natts);
1344  for (i = 0; i < desc->natts; ++i)
1345  {
1346  char *key;
1347  PyObject *volatile value;
1348  PLyObToDatum *att;
1349 
1350  if (desc->attrs[i]->attisdropped)
1351  {
1352  values[i] = (Datum) 0;
1353  nulls[i] = true;
1354  continue;
1355  }
1356 
1357  key = NameStr(desc->attrs[i]->attname);
1358  value = NULL;
1359  att = &info->out.r.atts[i];
1360  PG_TRY();
1361  {
1362  value = PyObject_GetAttrString(object, key);
1363  if (value == Py_None)
1364  {
1365  values[i] = (Datum) NULL;
1366  nulls[i] = true;
1367  }
1368  else if (value)
1369  {
1370  values[i] = (att->func) (att, -1, value, false);
1371  nulls[i] = false;
1372  }
1373  else
1374  {
1375  /*
1376  * No attribute for this column in the object.
1377  *
1378  * If we are parsing a composite type in an array, a likely
1379  * cause is that the function contained something like "[[123,
1380  * 'foo']]". Before PostgreSQL 10, that was interpreted as an
1381  * array, with a composite type (123, 'foo') in it. But now
1382  * it's interpreted as a two-dimensional array, and we try to
1383  * interpret "123" as the composite type. See also similar
1384  * heuristic in PLyObject_ToDatum().
1385  */
1386  ereport(ERROR,
1387  (errcode(ERRCODE_UNDEFINED_COLUMN),
1388  errmsg("attribute \"%s\" does not exist in Python object", key),
1389  inarray ?
1390  errhint("To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".") :
1391  errhint("To return null in a column, let the returned object have an attribute named after column with value None.")));
1392  }
1393 
1394  Py_XDECREF(value);
1395  value = NULL;
1396  }
1397  PG_CATCH();
1398  {
1399  Py_XDECREF(value);
1400  PG_RE_THROW();
1401  }
1402  PG_END_TRY();
1403  }
1404 
1405  tuple = heap_form_tuple(desc, values, nulls);
1406  result = heap_copy_tuple_as_datum(tuple, desc);
1407  heap_freetuple(tuple);
1408 
1409  pfree(values);
1410  pfree(nulls);
1411 
1412  return result;
1413 }
FmgrInfo typfunc
Definition: plpy_typeio.h:58
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
static Datum PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:745
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:588
TransactionId typrel_xmin
Definition: plpy_typeio.h:96
void PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:181
static PyObject * PLyInt_FromInt32(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:582
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
Oid tdtypeid
Definition: tupdesc.h:77
int errhint(const char *fmt,...)
Definition: elog.c:987
PLyDatumToOb * atts
Definition: plpy_typeio.h:35
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
#define VARDATA(PTR)
Definition: postgres.h:303
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void PLy_input_datum_func(PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:87
static int32 next
Definition: blutils.c:210
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
void PLy_typeinfo_init(PLyTypeInfo *arg, MemoryContext mcxt)
Definition: plpy_typeio.c:70
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1257
#define DatumGetInt32(X)
Definition: postgres.h:478
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:522
#define MAXDIM
Definition: c.h:419
#define PyObject_Bytes
Definition: plpython.h:87
void PLy_output_datum_func(PLyTypeInfo *arg, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:96
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
#define OIDOID
Definition: pg_type.h:328
#define PointerGetDatum(X)
Definition: postgres.h:562
#define NUMERICOID
Definition: pg_type.h:554
#define VARHDRSZ
Definition: c.h:445
#define DatumGetObjectId(X)
Definition: postgres.h:506
char * pstrdup(const char *in)
Definition: mcxt.c:1077
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:641
Form_pg_attribute * attrs
Definition: tupdesc.h:74
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define INT4OID
Definition: pg_type.h:316
int errcode(int sqlerrcode)
Definition: elog.c:575
void PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:105
char get_typtype(Oid typid)
Definition: lsyscache.c:2379
#define MemSet(start, val, len)
Definition: c.h:857
#define PyBytes_FromStringAndSize
Definition: plpython.h:85
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
return result
Definition: formatting.c:1633
#define DatumGetByteaPP(X)
Definition: fmgr.h:255
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
Oid typeidTypeRelid(Oid type_id)
Definition: parse_type.c:646
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:584
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:398
#define PyBytes_AsString
Definition: plpython.h:84
#define OidIsValid(objectId)
Definition: c.h:538
int natts
Definition: tupdesc.h:73
PLyObToDatumFunc func
Definition: plpy_typeio.h:57
int32 typmod
Definition: plpy_typeio.h:61
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
int32 tdtypmod
Definition: tupdesc.h:78
signed int int32
Definition: c.h:256
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1667
HeapTupleHeader t_data
Definition: htup.h:67
static PyObject * PLyInt_FromInt16(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:576
static Datum PLyObject_ToTransform(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:963
ItemPointerData typrel_tid
Definition: plpy_typeio.h:97
void pfree(void *pointer)
Definition: mcxt.c:950
static void PLy_input_datum_func2(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:437
PLyTypeInput in
Definition: plpy_typeio.h:86
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
static Datum PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:808
static Datum PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string, bool inarray)
Definition: plpy_typeio.c:1130
#define DatumGetCString(X)
Definition: postgres.h:572
static PyObject * PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:536
char * PLyObject_AsString(PyObject *plrv)
Definition: plpy_typeio.c:849
#define ARR_DIMS(a)
Definition: array.h:275
PLyObToDatum d
Definition: plpy_typeio.h:77
PyObject * PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)
Definition: plpy_typeio.c:280
PLyDatumToObFunc func
Definition: plpy_typeio.h:21
static struct @121 value
ItemPointerData t_self
Definition: htup.h:65
#define DatumGetInt64(X)
Definition: postgres.h:613
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
#define INT2OID
Definition: pg_type.h:308
static PyObject * PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:530
#define ARR_DATA_PTR(a)
Definition: array.h:303
PLyTypeOutput out
Definition: plpy_typeio.h:87
static PyObject * PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:604
int32 typmod
Definition: plpy_typeio.h:25
int errdetail(const char *fmt,...)
Definition: elog.c:873
FmgrInfo typfunc
Definition: plpy_typeio.h:22
#define DatumGetInt16(X)
Definition: postgres.h:450
#define DatumGetBool(X)
Definition: postgres.h:399
#define InvalidTransactionId
Definition: transam.h:31
struct PLyDatumToOb * elm
Definition: plpy_typeio.h:30
int16 typlen
Definition: plpy_typeio.h:28
#define RECORDOID
Definition: pg_type.h:680
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2404
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
#define ereport(elevel, rest)
Definition: elog.h:122
static PyObject * PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:542
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:656
#define PyBytes_Size
Definition: plpython.h:86
PLyProcedure * curr_proc
Definition: plpy_main.h:20
#define MaxAllocSize
Definition: memutils.h:40
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
uint8 bits8
Definition: c.h:275
#define FLOAT4OID
Definition: pg_type.h:416
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:878
static PyObject * PLyString_FromDatum(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:614
#define DatumGetFloat8(X)
Definition: postgres.h:734
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
FmgrInfo typtransform
Definition: plpy_typeio.h:23
PLyTupleToOb r
Definition: plpy_typeio.h:42
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
Definition: domains.c:326
static Datum PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object, bool inarray)
Definition: plpy_typeio.c:1329
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1623
#define BoolGetDatum(X)
Definition: postgres.h:408
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
MemoryContext mcxt
Definition: plpy_typeio.h:100
#define INT8OID
Definition: pg_type.h:304
#define PG_CATCH()
Definition: elog.h:293
static Datum PLyMapping_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *mapping)
Definition: plpy_typeio.c:1164
void PLy_output_record_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:251
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:630
#define Assert(condition)
Definition: c.h:675
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:598
#define DatumGetFloat4(X)
Definition: postgres.h:686
int is_rowtype
Definition: plpy_typeio.h:93
PLyObToTuple r
Definition: plpy_typeio.h:78
#define FLOAT8OID
Definition: pg_type.h:419
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
#define PG_RE_THROW()
Definition: elog.h:314
void * fn_extra
Definition: fmgr.h:64
#define BOOLOID
Definition: pg_type.h:288
static Datum PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence)
Definition: plpy_typeio.c:1240
#define ARR_NDIM(a)
Definition: array.h:271
PyObject * PLyUnicode_Bytes(PyObject *unicode)
Definition: plpy_util.c:26
static void PLy_output_datum_func2(PLyObToDatum *arg, MemoryContext arg_mcxt, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:365
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1893
#define BYTEAOID
Definition: pg_type.h:292
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:163
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2557
static PyObject * PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:624
static Datum PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:970
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
tuple list
Definition: sort-test.py:11
struct PLyObToDatum * elm
Definition: plpy_typeio.h:66
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
Datum PLyObject_ToCompositeDatum(PLyTypeInfo *info, TupleDesc desc, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:345
int i
Oid getTypeIOParam(HeapTuple typeTuple)
Definition: lsyscache.c:2053
#define FunctionCall1(flinfo, arg1)
Definition: fmgr.h:602
#define NameStr(name)
Definition: c.h:499
static PyObject * PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim, char **dataptr_p, bits8 **bitmap_p, int *bitmask_p)
Definition: plpy_typeio.c:670
void * arg
PLyObToDatum * atts
Definition: plpy_typeio.h:71
Definition: c.h:439
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1866
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3340
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:107
#define PG_TRY()
Definition: elog.h:284
static void PLySequence_ToArray_recurse(PLyObToDatum *elm, PyObject *list, int *dims, int ndim, int dim, Datum *elems, bool *nulls, int *currelem)
Definition: plpy_typeio.c:1083
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2271
PLyDatumToOb d
Definition: plpy_typeio.h:41
Definition: pg_list.h:45
#define ARR_NULLBITMAP(a)
Definition: array.h:281
static Datum PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:907
static Datum PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:764
#define PG_END_TRY()
Definition: elog.h:300
FmgrInfo typtransform
Definition: plpy_typeio.h:59
int16 typlen
Definition: plpy_typeio.h:64
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
Definition: plpy_main.c:407
#define DatumGetArrayTypeP(X)
Definition: array.h:242
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2075