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 = DatumGetByteaP(d);
607  char *str = VARDATA(txt);
608  size_t size = VARSIZE(txt) - VARHDRSZ;
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 would
651  * be the following: [0,0,0] elements through [0,0,k], then [0,1,0] through
652  * [0,1,k] till [0,m,k], then [1,0,0] through [1,0,k] till [1,m,k], and so on.
653  *
654  * In Python, there are no multi-dimensional lists as such, but they are
655  * represented as a list of lists. So a 3-d array of [n,m,k] elements is a
656  * list of n m-element arrays, each element of which is k-element array.
657  * PLyList_FromArray_recurse() builds the Python list for a single
658  * dimension, and recurses for the next inner dimension.
659  */
660  dataptr = ARR_DATA_PTR(array);
661  bitmap = ARR_NULLBITMAP(array);
662  bitmask = 1;
663 
664  return PLyList_FromArray_recurse(elm, dims, ndim, 0,
665  &dataptr, &bitmap, &bitmask);
666 }
667 
668 static PyObject *
669 PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
670  char **dataptr_p, bits8 **bitmap_p, int *bitmask_p)
671 {
672  int i;
673  PyObject *list;
674 
675  list = PyList_New(dims[dim]);
676 
677  if (dim < ndim - 1)
678  {
679  /* Outer dimension. Recurse for each inner slice. */
680  for (i = 0; i < dims[dim]; i++)
681  {
682  PyObject *sublist;
683 
684  sublist = PLyList_FromArray_recurse(elm, dims, ndim, dim + 1,
685  dataptr_p, bitmap_p, bitmask_p);
686  PyList_SET_ITEM(list, i, sublist);
687  }
688  }
689  else
690  {
691  /*
692  * Innermost dimension. Fill the list with the values from the array
693  * for this slice.
694  */
695  char *dataptr = *dataptr_p;
696  bits8 *bitmap = *bitmap_p;
697  int bitmask = *bitmask_p;
698 
699  for (i = 0; i < dims[dim]; i++)
700  {
701  /* checking for NULL */
702  if (bitmap && (*bitmap & bitmask) == 0)
703  {
704  Py_INCREF(Py_None);
705  PyList_SET_ITEM(list, i, Py_None);
706  }
707  else
708  {
709  Datum itemvalue;
710 
711  itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen);
712  PyList_SET_ITEM(list, i, elm->func(elm, itemvalue));
713  dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr);
714  dataptr = (char *) att_align_nominal(dataptr, elm->typalign);
715  }
716 
717  /* advance bitmap pointer if any */
718  if (bitmap)
719  {
720  bitmask <<= 1;
721  if (bitmask == 0x100 /* (1<<8) */ )
722  {
723  bitmap++;
724  bitmask = 1;
725  }
726  }
727  }
728 
729  *dataptr_p = dataptr;
730  *bitmap_p = bitmap;
731  *bitmask_p = bitmask;
732  }
733 
734  return list;
735 }
736 
737 /*
738  * Convert a Python object to a PostgreSQL bool datum. This can't go
739  * through the generic conversion function, because Python attaches a
740  * Boolean value to everything, more things than the PostgreSQL bool
741  * type can parse.
742  */
743 static Datum
744 PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
745 {
746  Datum rv;
747 
748  Assert(plrv != Py_None);
749  rv = BoolGetDatum(PyObject_IsTrue(plrv));
750 
751  if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
752  domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
753 
754  return rv;
755 }
756 
757 /*
758  * Convert a Python object to a PostgreSQL bytea datum. This doesn't
759  * go through the generic conversion function to circumvent problems
760  * with embedded nulls. And it's faster this way.
761  */
762 static Datum
763 PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
764 {
765  PyObject *volatile plrv_so = NULL;
766  Datum rv;
767 
768  Assert(plrv != Py_None);
769 
770  plrv_so = PyObject_Bytes(plrv);
771  if (!plrv_so)
772  PLy_elog(ERROR, "could not create bytes representation of Python object");
773 
774  PG_TRY();
775  {
776  char *plrv_sc = PyBytes_AsString(plrv_so);
777  size_t len = PyBytes_Size(plrv_so);
778  size_t size = len + VARHDRSZ;
779  bytea *result = palloc(size);
780 
781  SET_VARSIZE(result, size);
782  memcpy(VARDATA(result), plrv_sc, len);
783  rv = PointerGetDatum(result);
784  }
785  PG_CATCH();
786  {
787  Py_XDECREF(plrv_so);
788  PG_RE_THROW();
789  }
790  PG_END_TRY();
791 
792  Py_XDECREF(plrv_so);
793 
794  if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
795  domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
796 
797  return rv;
798 }
799 
800 
801 /*
802  * Convert a Python object to a composite type. First look up the type's
803  * description, then route the Python object through the conversion function
804  * for obtaining PostgreSQL tuples.
805  */
806 static Datum
807 PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
808 {
809  Datum rv;
810  PLyTypeInfo info;
811  TupleDesc desc;
812  MemoryContext cxt;
813 
814  if (typmod != -1)
815  elog(ERROR, "received unnamed record type as input");
816 
817  /* Create a dummy PLyTypeInfo */
819  "PL/Python temp context",
821  MemSet(&info, 0, sizeof(PLyTypeInfo));
822  PLy_typeinfo_init(&info, cxt);
823  /* Mark it as needing output routines lookup */
824  info.is_rowtype = 2;
825 
826  desc = lookup_rowtype_tupdesc(arg->typoid, arg->typmod);
827 
828  /*
829  * This will set up the dummy PLyTypeInfo's output conversion routines,
830  * since we left is_rowtype as 2. A future optimisation could be caching
831  * that info instead of looking it up every time a tuple is returned from
832  * the function.
833  */
834  rv = PLyObject_ToCompositeDatum(&info, desc, plrv, inarray);
835 
836  ReleaseTupleDesc(desc);
837 
838  MemoryContextDelete(cxt);
839 
840  return rv;
841 }
842 
843 
844 /*
845  * Convert Python object to C string in server encoding.
846  */
847 char *
848 PLyObject_AsString(PyObject *plrv)
849 {
850  PyObject *plrv_bo;
851  char *plrv_sc;
852  size_t plen;
853  size_t slen;
854 
855  if (PyUnicode_Check(plrv))
856  plrv_bo = PLyUnicode_Bytes(plrv);
857  else if (PyFloat_Check(plrv))
858  {
859  /* use repr() for floats, str() is lossy */
860 #if PY_MAJOR_VERSION >= 3
861  PyObject *s = PyObject_Repr(plrv);
862 
863  plrv_bo = PLyUnicode_Bytes(s);
864  Py_XDECREF(s);
865 #else
866  plrv_bo = PyObject_Repr(plrv);
867 #endif
868  }
869  else
870  {
871 #if PY_MAJOR_VERSION >= 3
872  PyObject *s = PyObject_Str(plrv);
873 
874  plrv_bo = PLyUnicode_Bytes(s);
875  Py_XDECREF(s);
876 #else
877  plrv_bo = PyObject_Str(plrv);
878 #endif
879  }
880  if (!plrv_bo)
881  PLy_elog(ERROR, "could not create string representation of Python object");
882 
883  plrv_sc = pstrdup(PyBytes_AsString(plrv_bo));
884  plen = PyBytes_Size(plrv_bo);
885  slen = strlen(plrv_sc);
886 
887  Py_XDECREF(plrv_bo);
888 
889  if (slen < plen)
890  ereport(ERROR,
891  (errcode(ERRCODE_DATATYPE_MISMATCH),
892  errmsg("could not convert Python object into cstring: Python string representation appears to contain null bytes")));
893  else if (slen > plen)
894  elog(ERROR, "could not convert Python object into cstring: Python string longer than reported length");
895  pg_verifymbstr(plrv_sc, slen, false);
896 
897  return plrv_sc;
898 }
899 
900 
901 /*
902  * Generic conversion function: Convert PyObject to cstring and
903  * cstring into PostgreSQL type.
904  */
905 static Datum
906 PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
907 {
908  char *str;
909 
910  Assert(plrv != Py_None);
911 
912  str = PLyObject_AsString(plrv);
913 
914  /*
915  * If we are parsing a composite type within an array, and the string
916  * isn't a valid record literal, there's a high chance that the function
917  * did something like:
918  *
919  * CREATE FUNCTION .. RETURNS comptype[] AS $$ return [['foo', 'bar']] $$
920  * LANGUAGE plpython;
921  *
922  * Before PostgreSQL 10, that was interpreted as a single-dimensional
923  * array, containing record ('foo', 'bar'). PostgreSQL 10 added support
924  * for multi-dimensional arrays, and it is now interpreted as a
925  * two-dimensional array, containing two records, 'foo', and 'bar'.
926  * record_in() will throw an error, because "foo" is not a valid record
927  * literal.
928  *
929  * To make that less confusing to users who are upgrading from older
930  * versions, try to give a hint in the typical instances of that. If we are
931  * parsing an array of composite types, and we see a string literal that
932  * is not a valid record literal, give a hint. We only want to give the
933  * hint in the narrow case of a malformed string literal, not any error
934  * from record_in(), so check for that case here specifically.
935  *
936  * This check better match the one in record_in(), so that we don't forbid
937  * literals that are actually valid!
938  */
939  if (inarray && arg->typfunc.fn_oid == F_RECORD_IN)
940  {
941  char *ptr = str;
942 
943  /* Allow leading whitespace */
944  while (*ptr && isspace((unsigned char) *ptr))
945  ptr++;
946  if (*ptr++ != '(')
947  ereport(ERROR,
948  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
949  errmsg("malformed record literal: \"%s\"", str),
950  errdetail("Missing left parenthesis."),
951  errhint("To return a composite type in an array, return the composite type as a Python tuple, e.g. \"[('foo')]\"")));
952  }
953 
954  return InputFunctionCall(&arg->typfunc,
955  str,
956  arg->typioparam,
957  typmod);
958 }
959 
960 
961 static Datum
962 PLyObject_ToTransform(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
963 {
964  return FunctionCall1(&arg->typtransform, PointerGetDatum(plrv));
965 }
966 
967 
968 static Datum
969 PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
970 {
971  ArrayType *array;
972  int i;
973  Datum *elems;
974  bool *nulls;
975  int64 len;
976  int ndim;
977  int dims[MAXDIM];
978  int lbs[MAXDIM];
979  int currelem;
980  Datum rv;
981  PyObject *pyptr = plrv;
982  PyObject *next;
983 
984  Assert(plrv != Py_None);
985 
986  /*
987  * Determine the number of dimensions, and their sizes.
988  */
989  ndim = 0;
990  len = 1;
991 
992  Py_INCREF(plrv);
993 
994  for (;;)
995  {
996  if (!PyList_Check(pyptr))
997  break;
998 
999  if (ndim == MAXDIM)
1000  PLy_elog(ERROR, "number of array dimensions exceeds the maximum allowed (%d)", MAXDIM);
1001 
1002  dims[ndim] = PySequence_Length(pyptr);
1003  if (dims[ndim] < 0)
1004  PLy_elog(ERROR, "cannot determine sequence length for function return value");
1005 
1006  if (dims[ndim] > MaxAllocSize)
1007  PLy_elog(ERROR, "array size exceeds the maximum allowed");
1008 
1009  len *= dims[ndim];
1010  if (len > MaxAllocSize)
1011  PLy_elog(ERROR, "array size exceeds the maximum allowed");
1012 
1013  if (dims[ndim] == 0)
1014  {
1015  /* empty sequence */
1016  break;
1017  }
1018 
1019  ndim++;
1020 
1021  next = PySequence_GetItem(pyptr, 0);
1022  Py_XDECREF(pyptr);
1023  pyptr = next;
1024  }
1025  Py_XDECREF(pyptr);
1026 
1027  /*
1028  * Check for zero dimensions. This happens if the object is a tuple or a
1029  * string, rather than a list, or is not a sequence at all. We don't map
1030  * tuples or strings to arrays in general, but in the first level, be
1031  * lenient, for historical reasons. So if the object is a sequence of any
1032  * kind, treat it as a one-dimensional array.
1033  */
1034  if (ndim == 0)
1035  {
1036  if (!PySequence_Check(plrv))
1037  PLy_elog(ERROR, "return value of function with array return type is not a Python sequence");
1038 
1039  ndim = 1;
1040  len = dims[0] = PySequence_Length(plrv);
1041  }
1042 
1043  /*
1044  * Traverse the Python lists, in depth-first order, and collect all the
1045  * elements at the bottom level into 'elems'/'nulls' arrays.
1046  */
1047  elems = palloc(sizeof(Datum) * len);
1048  nulls = palloc(sizeof(bool) * len);
1049  currelem = 0;
1050  PLySequence_ToArray_recurse(arg->elm, plrv,
1051  dims, ndim, 0,
1052  elems, nulls, &currelem);
1053 
1054  for (i = 0; i < ndim; i++)
1055  lbs[i] = 1;
1056 
1057  array = construct_md_array(elems,
1058  nulls,
1059  ndim,
1060  dims,
1061  lbs,
1063  arg->elm->typlen,
1064  arg->elm->typbyval,
1065  arg->elm->typalign);
1066 
1067  /*
1068  * If the result type is a domain of array, the resulting array must be
1069  * checked.
1070  */
1071  rv = PointerGetDatum(array);
1072  if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
1073  domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
1074  return rv;
1075 }
1076 
1077 /*
1078  * Helper function for PLySequence_ToArray. Traverse a Python list of lists in
1079  * depth-first order, storing the elements in 'elems'.
1080  */
1081 static void
1083  int *dims, int ndim, int dim,
1084  Datum *elems, bool *nulls, int *currelem)
1085 {
1086  int i;
1087 
1088  if (PySequence_Length(list) != dims[dim])
1089  PLy_elog(ERROR,
1090  "multidimensional arrays must have array expressions with matching dimensions. "
1091  "PL/Python function return value has sequence length %d while expected %d",
1092  (int) PySequence_Length(list), dims[dim]);
1093 
1094  if (dim < ndim - 1)
1095  {
1096  for (i = 0; i < dims[dim]; i++)
1097  {
1098  PyObject *sublist = PySequence_GetItem(list, i);
1099 
1100  PLySequence_ToArray_recurse(elm, sublist, dims, ndim, dim + 1,
1101  elems, nulls, currelem);
1102  Py_XDECREF(sublist);
1103  }
1104  }
1105  else
1106  {
1107  for (i = 0; i < dims[dim]; i++)
1108  {
1109  PyObject *obj = PySequence_GetItem(list, i);
1110 
1111  if (obj == Py_None)
1112  {
1113  nulls[*currelem] = true;
1114  elems[*currelem] = (Datum) 0;
1115  }
1116  else
1117  {
1118  nulls[*currelem] = false;
1119  elems[*currelem] = elm->func(elm, -1, obj, true);
1120  }
1121  Py_XDECREF(obj);
1122  (*currelem)++;
1123  }
1124  }
1125 }
1126 
1127 
1128 static Datum
1129 PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string, bool inarray)
1130 {
1131  Datum result;
1132  HeapTuple typeTup;
1133  PLyTypeInfo locinfo;
1135  MemoryContext cxt;
1136 
1137  /* Create a dummy PLyTypeInfo */
1139  "PL/Python temp context",
1141  MemSet(&locinfo, 0, sizeof(PLyTypeInfo));
1142  PLy_typeinfo_init(&locinfo, cxt);
1143 
1144  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(desc->tdtypeid));
1145  if (!HeapTupleIsValid(typeTup))
1146  elog(ERROR, "cache lookup failed for type %u", desc->tdtypeid);
1147 
1148  PLy_output_datum_func2(&locinfo.out.d, locinfo.mcxt, typeTup,
1149  exec_ctx->curr_proc->langid,
1150  exec_ctx->curr_proc->trftypes);
1151 
1152  ReleaseSysCache(typeTup);
1153 
1154  result = PLyObject_ToDatum(&locinfo.out.d, desc->tdtypmod, string, inarray);
1155 
1156  MemoryContextDelete(cxt);
1157 
1158  return result;
1159 }
1160 
1161 
1162 static Datum
1163 PLyMapping_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *mapping)
1164 {
1165  Datum result;
1166  HeapTuple tuple;
1167  Datum *values;
1168  bool *nulls;
1169  volatile int i;
1170 
1171  Assert(PyMapping_Check(mapping));
1172 
1173  if (info->is_rowtype == 2)
1174  PLy_output_tuple_funcs(info, desc);
1175  Assert(info->is_rowtype == 1);
1176 
1177  /* Build tuple */
1178  values = palloc(sizeof(Datum) * desc->natts);
1179  nulls = palloc(sizeof(bool) * desc->natts);
1180  for (i = 0; i < desc->natts; ++i)
1181  {
1182  char *key;
1183  PyObject *volatile value;
1184  PLyObToDatum *att;
1185 
1186  if (desc->attrs[i]->attisdropped)
1187  {
1188  values[i] = (Datum) 0;
1189  nulls[i] = true;
1190  continue;
1191  }
1192 
1193  key = NameStr(desc->attrs[i]->attname);
1194  value = NULL;
1195  att = &info->out.r.atts[i];
1196  PG_TRY();
1197  {
1198  value = PyMapping_GetItemString(mapping, key);
1199  if (value == Py_None)
1200  {
1201  values[i] = (Datum) NULL;
1202  nulls[i] = true;
1203  }
1204  else if (value)
1205  {
1206  values[i] = (att->func) (att, -1, value, false);
1207  nulls[i] = false;
1208  }
1209  else
1210  ereport(ERROR,
1211  (errcode(ERRCODE_UNDEFINED_COLUMN),
1212  errmsg("key \"%s\" not found in mapping", key),
1213  errhint("To return null in a column, "
1214  "add the value None to the mapping with the key named after the column.")));
1215 
1216  Py_XDECREF(value);
1217  value = NULL;
1218  }
1219  PG_CATCH();
1220  {
1221  Py_XDECREF(value);
1222  PG_RE_THROW();
1223  }
1224  PG_END_TRY();
1225  }
1226 
1227  tuple = heap_form_tuple(desc, values, nulls);
1228  result = heap_copy_tuple_as_datum(tuple, desc);
1229  heap_freetuple(tuple);
1230 
1231  pfree(values);
1232  pfree(nulls);
1233 
1234  return result;
1235 }
1236 
1237 
1238 static Datum
1239 PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence)
1240 {
1241  Datum result;
1242  HeapTuple tuple;
1243  Datum *values;
1244  bool *nulls;
1245  volatile int idx;
1246  volatile int i;
1247 
1248  Assert(PySequence_Check(sequence));
1249 
1250  /*
1251  * Check that sequence length is exactly same as PG tuple's. We actually
1252  * can ignore exceeding items or assume missing ones as null but to avoid
1253  * plpython developer's errors we are strict here
1254  */
1255  idx = 0;
1256  for (i = 0; i < desc->natts; i++)
1257  {
1258  if (!desc->attrs[i]->attisdropped)
1259  idx++;
1260  }
1261  if (PySequence_Length(sequence) != idx)
1262  ereport(ERROR,
1263  (errcode(ERRCODE_DATATYPE_MISMATCH),
1264  errmsg("length of returned sequence did not match number of columns in row")));
1265 
1266  if (info->is_rowtype == 2)
1267  PLy_output_tuple_funcs(info, desc);
1268  Assert(info->is_rowtype == 1);
1269 
1270  /* Build tuple */
1271  values = palloc(sizeof(Datum) * desc->natts);
1272  nulls = palloc(sizeof(bool) * desc->natts);
1273  idx = 0;
1274  for (i = 0; i < desc->natts; ++i)
1275  {
1276  PyObject *volatile value;
1277  PLyObToDatum *att;
1278 
1279  if (desc->attrs[i]->attisdropped)
1280  {
1281  values[i] = (Datum) 0;
1282  nulls[i] = true;
1283  continue;
1284  }
1285 
1286  value = NULL;
1287  att = &info->out.r.atts[i];
1288  PG_TRY();
1289  {
1290  value = PySequence_GetItem(sequence, idx);
1291  Assert(value);
1292  if (value == Py_None)
1293  {
1294  values[i] = (Datum) NULL;
1295  nulls[i] = true;
1296  }
1297  else if (value)
1298  {
1299  values[i] = (att->func) (att, -1, value, false);
1300  nulls[i] = false;
1301  }
1302 
1303  Py_XDECREF(value);
1304  value = NULL;
1305  }
1306  PG_CATCH();
1307  {
1308  Py_XDECREF(value);
1309  PG_RE_THROW();
1310  }
1311  PG_END_TRY();
1312 
1313  idx++;
1314  }
1315 
1316  tuple = heap_form_tuple(desc, values, nulls);
1317  result = heap_copy_tuple_as_datum(tuple, desc);
1318  heap_freetuple(tuple);
1319 
1320  pfree(values);
1321  pfree(nulls);
1322 
1323  return result;
1324 }
1325 
1326 
1327 static Datum
1328 PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object, bool inarray)
1329 {
1330  Datum result;
1331  HeapTuple tuple;
1332  Datum *values;
1333  bool *nulls;
1334  volatile int i;
1335 
1336  if (info->is_rowtype == 2)
1337  PLy_output_tuple_funcs(info, desc);
1338  Assert(info->is_rowtype == 1);
1339 
1340  /* Build tuple */
1341  values = palloc(sizeof(Datum) * desc->natts);
1342  nulls = palloc(sizeof(bool) * desc->natts);
1343  for (i = 0; i < desc->natts; ++i)
1344  {
1345  char *key;
1346  PyObject *volatile value;
1347  PLyObToDatum *att;
1348 
1349  if (desc->attrs[i]->attisdropped)
1350  {
1351  values[i] = (Datum) 0;
1352  nulls[i] = true;
1353  continue;
1354  }
1355 
1356  key = NameStr(desc->attrs[i]->attname);
1357  value = NULL;
1358  att = &info->out.r.atts[i];
1359  PG_TRY();
1360  {
1361  value = PyObject_GetAttrString(object, key);
1362  if (value == Py_None)
1363  {
1364  values[i] = (Datum) NULL;
1365  nulls[i] = true;
1366  }
1367  else if (value)
1368  {
1369  values[i] = (att->func) (att, -1, value, false);
1370  nulls[i] = false;
1371  }
1372  else
1373  {
1374  /*
1375  * No attribute for this column in the object.
1376  *
1377  * If we are parsing a composite type in an array, a likely
1378  * cause is that the function contained something like "[[123,
1379  * 'foo']]". Before PostgreSQL 10, that was interpreted as an
1380  * array, with a composite type (123, 'foo') in it. But now
1381  * it's interpreted as a two-dimensional array, and we try to
1382  * interpret "123" as the composite type. See also similar
1383  * heuristic in PLyObject_ToDatum().
1384  */
1385  ereport(ERROR,
1386  (errcode(ERRCODE_UNDEFINED_COLUMN),
1387  errmsg("attribute \"%s\" does not exist in Python object", key),
1388  inarray ?
1389  errhint("To return a composite type in an array, return the composite type as a Python tuple, e.g. \"[('foo')]\"") :
1390  errhint("To return null in a column, let the returned object have an attribute named after column with value None.")));
1391  }
1392 
1393  Py_XDECREF(value);
1394  value = NULL;
1395  }
1396  PG_CATCH();
1397  {
1398  Py_XDECREF(value);
1399  PG_RE_THROW();
1400  }
1401  PG_END_TRY();
1402  }
1403 
1404  tuple = heap_form_tuple(desc, values, nulls);
1405  result = heap_copy_tuple_as_datum(tuple, desc);
1406  heap_freetuple(tuple);
1407 
1408  pfree(values);
1409  pfree(nulls);
1410 
1411  return result;
1412 }
FmgrInfo typfunc
Definition: plpy_typeio.h:58
#define TYPTYPE_DOMAIN
Definition: pg_type.h:710
static Datum PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:744
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1840
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:588
static struct @76 value
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(PTR)
Definition: postgres.h:305
#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:62
#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:1245
#define DatumGetInt32(X)
Definition: postgres.h:480
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:522
#define MAXDIM
Definition: c.h:416
#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:709
#define OIDOID
Definition: pg_type.h:328
#define VARSIZE(PTR)
Definition: postgres.h:306
#define PointerGetDatum(X)
Definition: postgres.h:564
#define NUMERICOID
Definition: pg_type.h:542
#define VARHDRSZ
Definition: c.h:441
#define DatumGetObjectId(X)
Definition: postgres.h:508
char * pstrdup(const char *in)
Definition: mcxt.c:1165
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:2347
#define MemSet(start, val, len)
Definition: c.h:853
#define PyBytes_FromStringAndSize
Definition: plpython.h:85
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
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:555
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
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:534
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:149
int32 tdtypmod
Definition: tupdesc.h:78
signed int int32
Definition: c.h:253
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1926
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:962
ItemPointerData typrel_tid
Definition: plpy_typeio.h:97
void pfree(void *pointer)
Definition: mcxt.c:992
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:515
#define ERROR
Definition: elog.h:43
static Datum PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:807
static Datum PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string, bool inarray)
Definition: plpy_typeio.c:1129
#define DatumGetCString(X)
Definition: postgres.h:574
static PyObject * PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:536
char * PLyObject_AsString(PyObject *plrv)
Definition: plpy_typeio.c:848
#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
ItemPointerData t_self
Definition: htup.h:65
#define DatumGetByteaP(X)
Definition: fmgr.h:246
#define DatumGetInt64(X)
Definition: postgres.h:615
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
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:452
#define DatumGetBool(X)
Definition: postgres.h:401
#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:668
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2372
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:169
#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:272
#define FLOAT4OID
Definition: pg_type.h:408
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
void * palloc0(Size size)
Definition: mcxt.c:920
static PyObject * PLyString_FromDatum(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:614
#define DatumGetFloat8(X)
Definition: postgres.h:736
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
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:331
static Datum PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object, bool inarray)
Definition: plpy_typeio.c:1328
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1882
#define BoolGetDatum(X)
Definition: postgres.h:410
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:56
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:1163
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:226
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:630
#define Assert(condition)
Definition: c.h:671
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:598
#define DatumGetFloat4(X)
Definition: postgres.h:688
int is_rowtype
Definition: plpy_typeio.h:93
PLyObToTuple r
Definition: plpy_typeio.h:78
#define FLOAT8OID
Definition: pg_type.h:411
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
#define PG_RE_THROW()
Definition: elog.h:314
void * fn_extra
Definition: fmgr.h:61
#define BOOLOID
Definition: pg_type.h:288
static Datum PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence)
Definition: plpy_typeio.c:1239
#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:1861
#define BYTEAOID
Definition: pg_type.h:292
#define DatumGetPointer(X)
Definition: postgres.h:557
static Datum values[MAXATTR]
Definition: bootstrap.c:162
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2525
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:969
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:131
tuple list
Definition: sort-test.py:11
struct PLyObToDatum * elm
Definition: plpy_typeio.h:66
void * palloc(Size size)
Definition: mcxt.c:891
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:2021
#define FunctionCall1(flinfo, arg1)
Definition: fmgr.h:573
#define NameStr(name)
Definition: c.h:495
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:669
void * arg
PLyObToDatum * atts
Definition: plpy_typeio.h:71
Definition: c.h:435
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1866
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:330
#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:1082
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2239
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:906
static Datum PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:763
#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:2043