PostgreSQL Source Code  git master
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 "catalog/pg_type.h"
11 #include "funcapi.h"
12 #include "mb/pg_wchar.h"
13 #include "miscadmin.h"
14 #include "utils/array.h"
15 #include "utils/builtins.h"
16 #include "utils/fmgroids.h"
17 #include "utils/lsyscache.h"
18 #include "utils/memutils.h"
19 
20 #include "plpython.h"
21 
22 #include "plpy_typeio.h"
23 
24 #include "plpy_elog.h"
25 #include "plpy_main.h"
26 
27 
28 /* conversion from Datums to Python objects */
29 static PyObject *PLyBool_FromBool(PLyDatumToOb *arg, Datum d);
30 static PyObject *PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d);
31 static PyObject *PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d);
32 static PyObject *PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d);
33 static PyObject *PLyInt_FromInt16(PLyDatumToOb *arg, Datum d);
34 static PyObject *PLyInt_FromInt32(PLyDatumToOb *arg, Datum d);
35 static PyObject *PLyLong_FromInt64(PLyDatumToOb *arg, Datum d);
36 static PyObject *PLyLong_FromOid(PLyDatumToOb *arg, Datum d);
37 static PyObject *PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d);
38 static PyObject *PLyString_FromScalar(PLyDatumToOb *arg, Datum d);
39 static PyObject *PLyObject_FromTransform(PLyDatumToOb *arg, Datum d);
40 static PyObject *PLyList_FromArray(PLyDatumToOb *arg, Datum d);
41 static PyObject *PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
42  char **dataptr_p, bits8 **bitmap_p, int *bitmask_p);
43 static PyObject *PLyDict_FromComposite(PLyDatumToOb *arg, Datum d);
44 static PyObject *PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc);
45 
46 /* conversion from Python objects to Datums */
47 static Datum PLyObject_ToBool(PLyObToDatum *arg, PyObject *plrv,
48  bool *isnull, bool inarray);
49 static Datum PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv,
50  bool *isnull, bool inarray);
51 static Datum PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv,
52  bool *isnull, bool inarray);
53 static Datum PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv,
54  bool *isnull, bool inarray);
55 static Datum PLyObject_ToDomain(PLyObToDatum *arg, PyObject *plrv,
56  bool *isnull, bool inarray);
57 static Datum PLyObject_ToTransform(PLyObToDatum *arg, PyObject *plrv,
58  bool *isnull, bool inarray);
59 static Datum PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv,
60  bool *isnull, bool inarray);
61 static void PLySequence_ToArray_recurse(PLyObToDatum *elm, PyObject *list,
62  int *dims, int ndim, int dim,
63  Datum *elems, bool *nulls, int *currelem);
64 
65 /* conversion from Python objects to composite Datums */
66 static Datum PLyString_ToComposite(PLyObToDatum *arg, PyObject *string, bool inarray);
67 static Datum PLyMapping_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *mapping);
68 static Datum PLySequence_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *sequence);
69 static Datum PLyGenericObject_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *object, bool inarray);
70 
71 
72 /*
73  * Conversion functions. Remember output from Python is input to
74  * PostgreSQL, and vice versa.
75  */
76 
77 /*
78  * Perform input conversion, given correctly-set-up state information.
79  *
80  * This is the outer-level entry point for any input conversion. Internally,
81  * the conversion functions recurse directly to each other.
82  */
83 PyObject *
85 {
86  PyObject *result;
88  MemoryContext scratch_context = PLy_get_scratch_context(exec_ctx);
89  MemoryContext oldcontext;
90 
91  /*
92  * Do the work in the scratch context to avoid leaking memory from the
93  * datatype output function calls. (The individual PLyDatumToObFunc
94  * functions can't reset the scratch context, because they recurse and an
95  * inner one might clobber data an outer one still needs. So we do it
96  * once at the outermost recursion level.)
97  *
98  * We reset the scratch context before, not after, each conversion cycle.
99  * This way we aren't on the hook to release a Python refcount on the
100  * result object in case MemoryContextReset throws an error.
101  */
102  MemoryContextReset(scratch_context);
103 
104  oldcontext = MemoryContextSwitchTo(scratch_context);
105 
106  result = arg->func(arg, val);
107 
108  MemoryContextSwitchTo(oldcontext);
109 
110  return result;
111 }
112 
113 /*
114  * Perform output conversion, given correctly-set-up state information.
115  *
116  * This is the outer-level entry point for any output conversion. Internally,
117  * the conversion functions recurse directly to each other.
118  *
119  * The result, as well as any cruft generated along the way, are in the
120  * current memory context. Caller is responsible for cleanup.
121  */
122 Datum
123 PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
124 {
125  /* at outer level, we are not considering an array element */
126  return arg->func(arg, val, isnull, false);
127 }
128 
129 /*
130  * Transform a tuple into a Python dict object.
131  *
132  * Note: the tupdesc must match the one used to set up *arg. We could
133  * insist that this function lookup the tupdesc from what is in *arg,
134  * but in practice all callers have the right tupdesc available.
135  */
136 PyObject *
138 {
139  PyObject *dict;
141  MemoryContext scratch_context = PLy_get_scratch_context(exec_ctx);
142  MemoryContext oldcontext;
143 
144  /*
145  * As in PLy_input_convert, do the work in the scratch context.
146  */
147  MemoryContextReset(scratch_context);
148 
149  oldcontext = MemoryContextSwitchTo(scratch_context);
150 
151  dict = PLyDict_FromTuple(arg, tuple, desc);
152 
153  MemoryContextSwitchTo(oldcontext);
154 
155  return dict;
156 }
157 
158 /*
159  * Initialize, or re-initialize, per-column input info for a composite type.
160  *
161  * This is separate from PLy_input_setup_func() because in cases involving
162  * anonymous record types, we need to be passed the tupdesc explicitly.
163  * It's caller's responsibility that the tupdesc has adequate lifespan
164  * in such cases. If the tupdesc is for a named composite or registered
165  * record type, it does not need to be long-lived.
166  */
167 void
169 {
170  int i;
171 
172  /* We should be working on a previously-set-up struct */
174 
175  /* Save pointer to tupdesc, but only if this is an anonymous record type */
176  if (arg->typoid == RECORDOID && arg->typmod < 0)
177  arg->u.tuple.recdesc = desc;
178 
179  /* (Re)allocate atts array as needed */
180  if (arg->u.tuple.natts != desc->natts)
181  {
182  if (arg->u.tuple.atts)
183  pfree(arg->u.tuple.atts);
184  arg->u.tuple.natts = desc->natts;
185  arg->u.tuple.atts = (PLyDatumToOb *)
187  desc->natts * sizeof(PLyDatumToOb));
188  }
189 
190  /* Fill the atts entries, except for dropped columns */
191  for (i = 0; i < desc->natts; i++)
192  {
193  Form_pg_attribute attr = TupleDescAttr(desc, i);
194  PLyDatumToOb *att = &arg->u.tuple.atts[i];
195 
196  if (attr->attisdropped)
197  continue;
198 
199  if (att->typoid == attr->atttypid && att->typmod == attr->atttypmod)
200  continue; /* already set up this entry */
201 
202  PLy_input_setup_func(att, arg->mcxt,
203  attr->atttypid, attr->atttypmod,
204  proc);
205  }
206 }
207 
208 /*
209  * Initialize, or re-initialize, per-column output info for a composite type.
210  *
211  * This is separate from PLy_output_setup_func() because in cases involving
212  * anonymous record types, we need to be passed the tupdesc explicitly.
213  * It's caller's responsibility that the tupdesc has adequate lifespan
214  * in such cases. If the tupdesc is for a named composite or registered
215  * record type, it does not need to be long-lived.
216  */
217 void
219 {
220  int i;
221 
222  /* We should be working on a previously-set-up struct */
224 
225  /* Save pointer to tupdesc, but only if this is an anonymous record type */
226  if (arg->typoid == RECORDOID && arg->typmod < 0)
227  arg->u.tuple.recdesc = desc;
228 
229  /* (Re)allocate atts array as needed */
230  if (arg->u.tuple.natts != desc->natts)
231  {
232  if (arg->u.tuple.atts)
233  pfree(arg->u.tuple.atts);
234  arg->u.tuple.natts = desc->natts;
235  arg->u.tuple.atts = (PLyObToDatum *)
237  desc->natts * sizeof(PLyObToDatum));
238  }
239 
240  /* Fill the atts entries, except for dropped columns */
241  for (i = 0; i < desc->natts; i++)
242  {
243  Form_pg_attribute attr = TupleDescAttr(desc, i);
244  PLyObToDatum *att = &arg->u.tuple.atts[i];
245 
246  if (attr->attisdropped)
247  continue;
248 
249  if (att->typoid == attr->atttypid && att->typmod == attr->atttypmod)
250  continue; /* already set up this entry */
251 
252  PLy_output_setup_func(att, arg->mcxt,
253  attr->atttypid, attr->atttypmod,
254  proc);
255  }
256 }
257 
258 /*
259  * Set up output info for a PL/Python function returning record.
260  *
261  * Note: the given tupdesc is not necessarily long-lived.
262  */
263 void
265 {
266  /* Makes no sense unless RECORD */
267  Assert(arg->typoid == RECORDOID);
268  Assert(desc->tdtypeid == RECORDOID);
269 
270  /*
271  * Bless the record type if not already done. We'd have to do this anyway
272  * to return a tuple, so we might as well force the issue so we can use
273  * the known-record-type code path.
274  */
275  BlessTupleDesc(desc);
276 
277  /*
278  * Update arg->typmod, and clear the recdesc link if it's changed. The
279  * next call of PLyObject_ToComposite will look up a long-lived tupdesc
280  * for the record type.
281  */
282  arg->typmod = desc->tdtypmod;
283  if (arg->u.tuple.recdesc &&
284  arg->u.tuple.recdesc->tdtypmod != arg->typmod)
285  arg->u.tuple.recdesc = NULL;
286 
287  /* Update derived data if necessary */
288  PLy_output_setup_tuple(arg, desc, proc);
289 }
290 
291 /*
292  * Recursively initialize the PLyObToDatum structure(s) needed to construct
293  * a SQL value of the specified typeOid/typmod from a Python value.
294  * (But note that at this point we may have RECORDOID/-1, ie, an indeterminate
295  * record type.)
296  * proc is used to look up transform functions.
297  */
298 void
300  Oid typeOid, int32 typmod,
301  PLyProcedure *proc)
302 {
303  TypeCacheEntry *typentry;
304  char typtype;
305  Oid trfuncid;
306  Oid typinput;
307 
308  /* Since this is recursive, it could theoretically be driven to overflow */
310 
311  arg->typoid = typeOid;
312  arg->typmod = typmod;
313  arg->mcxt = arg_mcxt;
314 
315  /*
316  * Fetch typcache entry for the target type, asking for whatever info
317  * we'll need later. RECORD is a special case: just treat it as composite
318  * without bothering with the typcache entry.
319  */
320  if (typeOid != RECORDOID)
321  {
322  typentry = lookup_type_cache(typeOid, TYPECACHE_DOMAIN_BASE_INFO);
323  typtype = typentry->typtype;
324  arg->typbyval = typentry->typbyval;
325  arg->typlen = typentry->typlen;
326  arg->typalign = typentry->typalign;
327  }
328  else
329  {
330  typentry = NULL;
331  typtype = TYPTYPE_COMPOSITE;
332  /* hard-wired knowledge about type RECORD: */
333  arg->typbyval = false;
334  arg->typlen = -1;
335  arg->typalign = 'd';
336  }
337 
338  /*
339  * Choose conversion method. Note that transform functions are checked
340  * for composite and scalar types, but not for arrays or domains. This is
341  * somewhat historical, but we'd have a problem allowing them on domains,
342  * since we drill down through all levels of a domain nest without looking
343  * at the intermediate levels at all.
344  */
345  if (typtype == TYPTYPE_DOMAIN)
346  {
347  /* Domain */
348  arg->func = PLyObject_ToDomain;
349  arg->u.domain.domain_info = NULL;
350  /* Recursively set up conversion info for the element type */
351  arg->u.domain.base = (PLyObToDatum *)
352  MemoryContextAllocZero(arg_mcxt, sizeof(PLyObToDatum));
353  PLy_output_setup_func(arg->u.domain.base, arg_mcxt,
354  typentry->domainBaseType,
355  typentry->domainBaseTypmod,
356  proc);
357  }
358  else if (typentry &&
359  OidIsValid(typentry->typelem) && typentry->typlen == -1)
360  {
361  /* Standard varlena array (cf. get_element_type) */
362  arg->func = PLySequence_ToArray;
363  /* Get base type OID to insert into constructed array */
364  /* (note this might not be the same as the immediate child type) */
365  arg->u.array.elmbasetype = getBaseType(typentry->typelem);
366  /* Recursively set up conversion info for the element type */
367  arg->u.array.elm = (PLyObToDatum *)
368  MemoryContextAllocZero(arg_mcxt, sizeof(PLyObToDatum));
369  PLy_output_setup_func(arg->u.array.elm, arg_mcxt,
370  typentry->typelem, typmod,
371  proc);
372  }
373  else if ((trfuncid = get_transform_tosql(typeOid,
374  proc->langid,
375  proc->trftypes)))
376  {
378  fmgr_info_cxt(trfuncid, &arg->u.transform.typtransform, arg_mcxt);
379  }
380  else if (typtype == TYPTYPE_COMPOSITE)
381  {
382  /* Named composite type, or RECORD */
384  /* We'll set up the per-field data later */
385  arg->u.tuple.recdesc = NULL;
386  arg->u.tuple.typentry = typentry;
388  arg->u.tuple.atts = NULL;
389  arg->u.tuple.natts = 0;
390  /* Mark this invalid till needed, too */
392  }
393  else
394  {
395  /* Scalar type, but we have a couple of special cases */
396  switch (typeOid)
397  {
398  case BOOLOID:
399  arg->func = PLyObject_ToBool;
400  break;
401  case BYTEAOID:
402  arg->func = PLyObject_ToBytea;
403  break;
404  default:
405  arg->func = PLyObject_ToScalar;
406  getTypeInputInfo(typeOid, &typinput, &arg->u.scalar.typioparam);
407  fmgr_info_cxt(typinput, &arg->u.scalar.typfunc, arg_mcxt);
408  break;
409  }
410  }
411 }
412 
413 /*
414  * Recursively initialize the PLyDatumToOb structure(s) needed to construct
415  * a Python value from a SQL value of the specified typeOid/typmod.
416  * (But note that at this point we may have RECORDOID/-1, ie, an indeterminate
417  * record type.)
418  * proc is used to look up transform functions.
419  */
420 void
422  Oid typeOid, int32 typmod,
423  PLyProcedure *proc)
424 {
425  TypeCacheEntry *typentry;
426  char typtype;
427  Oid trfuncid;
428  Oid typoutput;
429  bool typisvarlena;
430 
431  /* Since this is recursive, it could theoretically be driven to overflow */
433 
434  arg->typoid = typeOid;
435  arg->typmod = typmod;
436  arg->mcxt = arg_mcxt;
437 
438  /*
439  * Fetch typcache entry for the target type, asking for whatever info
440  * we'll need later. RECORD is a special case: just treat it as composite
441  * without bothering with the typcache entry.
442  */
443  if (typeOid != RECORDOID)
444  {
445  typentry = lookup_type_cache(typeOid, TYPECACHE_DOMAIN_BASE_INFO);
446  typtype = typentry->typtype;
447  arg->typbyval = typentry->typbyval;
448  arg->typlen = typentry->typlen;
449  arg->typalign = typentry->typalign;
450  }
451  else
452  {
453  typentry = NULL;
454  typtype = TYPTYPE_COMPOSITE;
455  /* hard-wired knowledge about type RECORD: */
456  arg->typbyval = false;
457  arg->typlen = -1;
458  arg->typalign = 'd';
459  }
460 
461  /*
462  * Choose conversion method. Note that transform functions are checked
463  * for composite and scalar types, but not for arrays or domains. This is
464  * somewhat historical, but we'd have a problem allowing them on domains,
465  * since we drill down through all levels of a domain nest without looking
466  * at the intermediate levels at all.
467  */
468  if (typtype == TYPTYPE_DOMAIN)
469  {
470  /* Domain --- we don't care, just recurse down to the base type */
471  PLy_input_setup_func(arg, arg_mcxt,
472  typentry->domainBaseType,
473  typentry->domainBaseTypmod,
474  proc);
475  }
476  else if (typentry &&
477  OidIsValid(typentry->typelem) && typentry->typlen == -1)
478  {
479  /* Standard varlena array (cf. get_element_type) */
480  arg->func = PLyList_FromArray;
481  /* Recursively set up conversion info for the element type */
482  arg->u.array.elm = (PLyDatumToOb *)
483  MemoryContextAllocZero(arg_mcxt, sizeof(PLyDatumToOb));
484  PLy_input_setup_func(arg->u.array.elm, arg_mcxt,
485  typentry->typelem, typmod,
486  proc);
487  }
488  else if ((trfuncid = get_transform_fromsql(typeOid,
489  proc->langid,
490  proc->trftypes)))
491  {
493  fmgr_info_cxt(trfuncid, &arg->u.transform.typtransform, arg_mcxt);
494  }
495  else if (typtype == TYPTYPE_COMPOSITE)
496  {
497  /* Named composite type, or RECORD */
499  /* We'll set up the per-field data later */
500  arg->u.tuple.recdesc = NULL;
501  arg->u.tuple.typentry = typentry;
503  arg->u.tuple.atts = NULL;
504  arg->u.tuple.natts = 0;
505  }
506  else
507  {
508  /* Scalar type, but we have a couple of special cases */
509  switch (typeOid)
510  {
511  case BOOLOID:
512  arg->func = PLyBool_FromBool;
513  break;
514  case FLOAT4OID:
515  arg->func = PLyFloat_FromFloat4;
516  break;
517  case FLOAT8OID:
518  arg->func = PLyFloat_FromFloat8;
519  break;
520  case NUMERICOID:
522  break;
523  case INT2OID:
524  arg->func = PLyInt_FromInt16;
525  break;
526  case INT4OID:
527  arg->func = PLyInt_FromInt32;
528  break;
529  case INT8OID:
530  arg->func = PLyLong_FromInt64;
531  break;
532  case OIDOID:
533  arg->func = PLyLong_FromOid;
534  break;
535  case BYTEAOID:
536  arg->func = PLyBytes_FromBytea;
537  break;
538  default:
539  arg->func = PLyString_FromScalar;
540  getTypeOutputInfo(typeOid, &typoutput, &typisvarlena);
541  fmgr_info_cxt(typoutput, &arg->u.scalar.typfunc, arg_mcxt);
542  break;
543  }
544  }
545 }
546 
547 
548 /*
549  * Special-purpose input converters.
550  */
551 
552 static PyObject *
554 {
555  if (DatumGetBool(d))
556  Py_RETURN_TRUE;
557  Py_RETURN_FALSE;
558 }
559 
560 static PyObject *
562 {
563  return PyFloat_FromDouble(DatumGetFloat4(d));
564 }
565 
566 static PyObject *
568 {
569  return PyFloat_FromDouble(DatumGetFloat8(d));
570 }
571 
572 static PyObject *
574 {
575  static PyObject *decimal_constructor;
576  char *str;
577  PyObject *pyvalue;
578 
579  /* Try to import cdecimal. If it doesn't exist, fall back to decimal. */
580  if (!decimal_constructor)
581  {
582  PyObject *decimal_module;
583 
584  decimal_module = PyImport_ImportModule("cdecimal");
585  if (!decimal_module)
586  {
587  PyErr_Clear();
588  decimal_module = PyImport_ImportModule("decimal");
589  }
590  if (!decimal_module)
591  PLy_elog(ERROR, "could not import a module for Decimal constructor");
592 
593  decimal_constructor = PyObject_GetAttrString(decimal_module, "Decimal");
594  if (!decimal_constructor)
595  PLy_elog(ERROR, "no Decimal attribute in module");
596  }
597 
599  pyvalue = PyObject_CallFunction(decimal_constructor, "s", str);
600  if (!pyvalue)
601  PLy_elog(ERROR, "conversion from numeric to Decimal failed");
602 
603  return pyvalue;
604 }
605 
606 static PyObject *
608 {
609  return PyInt_FromLong(DatumGetInt16(d));
610 }
611 
612 static PyObject *
614 {
615  return PyInt_FromLong(DatumGetInt32(d));
616 }
617 
618 static PyObject *
620 {
621  return PyLong_FromLongLong(DatumGetInt64(d));
622 }
623 
624 static PyObject *
626 {
627  return PyLong_FromUnsignedLong(DatumGetObjectId(d));
628 }
629 
630 static PyObject *
632 {
633  text *txt = DatumGetByteaPP(d);
634  char *str = VARDATA_ANY(txt);
635  size_t size = VARSIZE_ANY_EXHDR(txt);
636 
637  return PyBytes_FromStringAndSize(str, size);
638 }
639 
640 
641 /*
642  * Generic input conversion using a SQL type's output function.
643  */
644 static PyObject *
646 {
647  char *x = OutputFunctionCall(&arg->u.scalar.typfunc, d);
648  PyObject *r = PyString_FromString(x);
649 
650  pfree(x);
651  return r;
652 }
653 
654 /*
655  * Convert using a from-SQL transform function.
656  */
657 static PyObject *
659 {
660  Datum t;
661 
662  t = FunctionCall1(&arg->u.transform.typtransform, d);
663  return (PyObject *) DatumGetPointer(t);
664 }
665 
666 /*
667  * Convert a SQL array to a Python list.
668  */
669 static PyObject *
671 {
672  ArrayType *array = DatumGetArrayTypeP(d);
673  PLyDatumToOb *elm = arg->u.array.elm;
674  int ndim;
675  int *dims;
676  char *dataptr;
677  bits8 *bitmap;
678  int bitmask;
679 
680  if (ARR_NDIM(array) == 0)
681  return PyList_New(0);
682 
683  /* Array dimensions and left bounds */
684  ndim = ARR_NDIM(array);
685  dims = ARR_DIMS(array);
686  Assert(ndim < MAXDIM);
687 
688  /*
689  * We iterate the SQL array in the physical order it's stored in the
690  * datum. For example, for a 3-dimensional array the order of iteration
691  * would be the following: [0,0,0] elements through [0,0,k], then [0,1,0]
692  * through [0,1,k] till [0,m,k], then [1,0,0] through [1,0,k] till
693  * [1,m,k], and so on.
694  *
695  * In Python, there are no multi-dimensional lists as such, but they are
696  * represented as a list of lists. So a 3-d array of [n,m,k] elements is a
697  * list of n m-element arrays, each element of which is k-element array.
698  * PLyList_FromArray_recurse() builds the Python list for a single
699  * dimension, and recurses for the next inner dimension.
700  */
701  dataptr = ARR_DATA_PTR(array);
702  bitmap = ARR_NULLBITMAP(array);
703  bitmask = 1;
704 
705  return PLyList_FromArray_recurse(elm, dims, ndim, 0,
706  &dataptr, &bitmap, &bitmask);
707 }
708 
709 static PyObject *
710 PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
711  char **dataptr_p, bits8 **bitmap_p, int *bitmask_p)
712 {
713  int i;
714  PyObject *list;
715 
716  list = PyList_New(dims[dim]);
717  if (!list)
718  return NULL;
719 
720  if (dim < ndim - 1)
721  {
722  /* Outer dimension. Recurse for each inner slice. */
723  for (i = 0; i < dims[dim]; i++)
724  {
725  PyObject *sublist;
726 
727  sublist = PLyList_FromArray_recurse(elm, dims, ndim, dim + 1,
728  dataptr_p, bitmap_p, bitmask_p);
729  PyList_SET_ITEM(list, i, sublist);
730  }
731  }
732  else
733  {
734  /*
735  * Innermost dimension. Fill the list with the values from the array
736  * for this slice.
737  */
738  char *dataptr = *dataptr_p;
739  bits8 *bitmap = *bitmap_p;
740  int bitmask = *bitmask_p;
741 
742  for (i = 0; i < dims[dim]; i++)
743  {
744  /* checking for NULL */
745  if (bitmap && (*bitmap & bitmask) == 0)
746  {
747  Py_INCREF(Py_None);
748  PyList_SET_ITEM(list, i, Py_None);
749  }
750  else
751  {
752  Datum itemvalue;
753 
754  itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen);
755  PyList_SET_ITEM(list, i, elm->func(elm, itemvalue));
756  dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr);
757  dataptr = (char *) att_align_nominal(dataptr, elm->typalign);
758  }
759 
760  /* advance bitmap pointer if any */
761  if (bitmap)
762  {
763  bitmask <<= 1;
764  if (bitmask == 0x100 /* (1<<8) */ )
765  {
766  bitmap++;
767  bitmask = 1;
768  }
769  }
770  }
771 
772  *dataptr_p = dataptr;
773  *bitmap_p = bitmap;
774  *bitmask_p = bitmask;
775  }
776 
777  return list;
778 }
779 
780 /*
781  * Convert a composite SQL value to a Python dict.
782  */
783 static PyObject *
785 {
786  PyObject *dict;
787  HeapTupleHeader td;
788  Oid tupType;
789  int32 tupTypmod;
790  TupleDesc tupdesc;
791  HeapTupleData tmptup;
792 
793  td = DatumGetHeapTupleHeader(d);
794  /* Extract rowtype info and find a tupdesc */
795  tupType = HeapTupleHeaderGetTypeId(td);
796  tupTypmod = HeapTupleHeaderGetTypMod(td);
797  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
798 
799  /* Set up I/O funcs if not done yet */
800  PLy_input_setup_tuple(arg, tupdesc,
801  PLy_current_execution_context()->curr_proc);
802 
803  /* Build a temporary HeapTuple control structure */
805  tmptup.t_data = td;
806 
807  dict = PLyDict_FromTuple(arg, &tmptup, tupdesc);
808 
809  ReleaseTupleDesc(tupdesc);
810 
811  return dict;
812 }
813 
814 /*
815  * Transform a tuple into a Python dict object.
816  */
817 static PyObject *
819 {
820  PyObject *volatile dict;
821 
822  /* Simple sanity check that desc matches */
823  Assert(desc->natts == arg->u.tuple.natts);
824 
825  dict = PyDict_New();
826  if (dict == NULL)
827  return NULL;
828 
829  PG_TRY();
830  {
831  int i;
832 
833  for (i = 0; i < arg->u.tuple.natts; i++)
834  {
835  PLyDatumToOb *att = &arg->u.tuple.atts[i];
836  Form_pg_attribute attr = TupleDescAttr(desc, i);
837  char *key;
838  Datum vattr;
839  bool is_null;
840  PyObject *value;
841 
842  if (attr->attisdropped)
843  continue;
844 
845  key = NameStr(attr->attname);
846  vattr = heap_getattr(tuple, (i + 1), desc, &is_null);
847 
848  if (is_null)
849  PyDict_SetItemString(dict, key, Py_None);
850  else
851  {
852  value = att->func(att, vattr);
853  PyDict_SetItemString(dict, key, value);
854  Py_DECREF(value);
855  }
856  }
857  }
858  PG_CATCH();
859  {
860  Py_DECREF(dict);
861  PG_RE_THROW();
862  }
863  PG_END_TRY();
864 
865  return dict;
866 }
867 
868 /*
869  * Convert a Python object to a PostgreSQL bool datum. This can't go
870  * through the generic conversion function, because Python attaches a
871  * Boolean value to everything, more things than the PostgreSQL bool
872  * type can parse.
873  */
874 static Datum
876  bool *isnull, bool inarray)
877 {
878  if (plrv == Py_None)
879  {
880  *isnull = true;
881  return (Datum) 0;
882  }
883  *isnull = false;
884  return BoolGetDatum(PyObject_IsTrue(plrv));
885 }
886 
887 /*
888  * Convert a Python object to a PostgreSQL bytea datum. This doesn't
889  * go through the generic conversion function to circumvent problems
890  * with embedded nulls. And it's faster this way.
891  */
892 static Datum
894  bool *isnull, bool inarray)
895 {
896  PyObject *volatile plrv_so = NULL;
897  Datum rv;
898 
899  if (plrv == Py_None)
900  {
901  *isnull = true;
902  return (Datum) 0;
903  }
904  *isnull = false;
905 
906  plrv_so = PyObject_Bytes(plrv);
907  if (!plrv_so)
908  PLy_elog(ERROR, "could not create bytes representation of Python object");
909 
910  PG_TRY();
911  {
912  char *plrv_sc = PyBytes_AsString(plrv_so);
913  size_t len = PyBytes_Size(plrv_so);
914  size_t size = len + VARHDRSZ;
915  bytea *result = palloc(size);
916 
917  SET_VARSIZE(result, size);
918  memcpy(VARDATA(result), plrv_sc, len);
919  rv = PointerGetDatum(result);
920  }
921  PG_CATCH();
922  {
923  Py_XDECREF(plrv_so);
924  PG_RE_THROW();
925  }
926  PG_END_TRY();
927 
928  Py_XDECREF(plrv_so);
929 
930  return rv;
931 }
932 
933 
934 /*
935  * Convert a Python object to a composite type. First look up the type's
936  * description, then route the Python object through the conversion function
937  * for obtaining PostgreSQL tuples.
938  */
939 static Datum
941  bool *isnull, bool inarray)
942 {
943  Datum rv;
944  TupleDesc desc;
945 
946  if (plrv == Py_None)
947  {
948  *isnull = true;
949  return (Datum) 0;
950  }
951  *isnull = false;
952 
953  /*
954  * The string conversion case doesn't require a tupdesc, nor per-field
955  * conversion data, so just go for it if that's the case to use.
956  */
957  if (PyString_Check(plrv) || PyUnicode_Check(plrv))
958  return PLyString_ToComposite(arg, plrv, inarray);
959 
960  /*
961  * If we're dealing with a named composite type, we must look up the
962  * tupdesc every time, to protect against possible changes to the type.
963  * RECORD types can't change between calls; but we must still be willing
964  * to set up the info the first time, if nobody did yet.
965  */
966  if (arg->typoid != RECORDOID)
967  {
968  desc = lookup_rowtype_tupdesc(arg->typoid, arg->typmod);
969  /* We should have the descriptor of the type's typcache entry */
970  Assert(desc == arg->u.tuple.typentry->tupDesc);
971  /* Detect change of descriptor, update cache if needed */
972  if (arg->u.tuple.tupdescid != arg->u.tuple.typentry->tupDesc_identifier)
973  {
974  PLy_output_setup_tuple(arg, desc,
975  PLy_current_execution_context()->curr_proc);
977  }
978  }
979  else
980  {
981  desc = arg->u.tuple.recdesc;
982  if (desc == NULL)
983  {
984  desc = lookup_rowtype_tupdesc(arg->typoid, arg->typmod);
985  arg->u.tuple.recdesc = desc;
986  }
987  else
988  {
989  /* Pin descriptor to match unpin below */
990  PinTupleDesc(desc);
991  }
992  }
993 
994  /* Simple sanity check on our caching */
995  Assert(desc->natts == arg->u.tuple.natts);
996 
997  /*
998  * Convert, using the appropriate method depending on the type of the
999  * supplied Python object.
1000  */
1001  if (PySequence_Check(plrv))
1002  /* composite type as sequence (tuple, list etc) */
1003  rv = PLySequence_ToComposite(arg, desc, plrv);
1004  else if (PyMapping_Check(plrv))
1005  /* composite type as mapping (currently only dict) */
1006  rv = PLyMapping_ToComposite(arg, desc, plrv);
1007  else
1008  /* returned as smth, must provide method __getattr__(name) */
1009  rv = PLyGenericObject_ToComposite(arg, desc, plrv, inarray);
1010 
1011  ReleaseTupleDesc(desc);
1012 
1013  return rv;
1014 }
1015 
1016 
1017 /*
1018  * Convert Python object to C string in server encoding.
1019  *
1020  * Note: this is exported for use by add-on transform modules.
1021  */
1022 char *
1023 PLyObject_AsString(PyObject *plrv)
1024 {
1025  PyObject *plrv_bo;
1026  char *plrv_sc;
1027  size_t plen;
1028  size_t slen;
1029 
1030  if (PyUnicode_Check(plrv))
1031  plrv_bo = PLyUnicode_Bytes(plrv);
1032  else if (PyFloat_Check(plrv))
1033  {
1034  /* use repr() for floats, str() is lossy */
1035 #if PY_MAJOR_VERSION >= 3
1036  PyObject *s = PyObject_Repr(plrv);
1037 
1038  plrv_bo = PLyUnicode_Bytes(s);
1039  Py_XDECREF(s);
1040 #else
1041  plrv_bo = PyObject_Repr(plrv);
1042 #endif
1043  }
1044  else
1045  {
1046 #if PY_MAJOR_VERSION >= 3
1047  PyObject *s = PyObject_Str(plrv);
1048 
1049  plrv_bo = PLyUnicode_Bytes(s);
1050  Py_XDECREF(s);
1051 #else
1052  plrv_bo = PyObject_Str(plrv);
1053 #endif
1054  }
1055  if (!plrv_bo)
1056  PLy_elog(ERROR, "could not create string representation of Python object");
1057 
1058  plrv_sc = pstrdup(PyBytes_AsString(plrv_bo));
1059  plen = PyBytes_Size(plrv_bo);
1060  slen = strlen(plrv_sc);
1061 
1062  Py_XDECREF(plrv_bo);
1063 
1064  if (slen < plen)
1065  ereport(ERROR,
1066  (errcode(ERRCODE_DATATYPE_MISMATCH),
1067  errmsg("could not convert Python object into cstring: Python string representation appears to contain null bytes")));
1068  else if (slen > plen)
1069  elog(ERROR, "could not convert Python object into cstring: Python string longer than reported length");
1070  pg_verifymbstr(plrv_sc, slen, false);
1071 
1072  return plrv_sc;
1073 }
1074 
1075 
1076 /*
1077  * Generic output conversion function: convert PyObject to cstring and
1078  * cstring into PostgreSQL type.
1079  */
1080 static Datum
1082  bool *isnull, bool inarray)
1083 {
1084  char *str;
1085 
1086  if (plrv == Py_None)
1087  {
1088  *isnull = true;
1089  return (Datum) 0;
1090  }
1091  *isnull = false;
1092 
1093  str = PLyObject_AsString(plrv);
1094 
1095  return InputFunctionCall(&arg->u.scalar.typfunc,
1096  str,
1097  arg->u.scalar.typioparam,
1098  arg->typmod);
1099 }
1100 
1101 
1102 /*
1103  * Convert to a domain type.
1104  */
1105 static Datum
1107  bool *isnull, bool inarray)
1108 {
1109  Datum result;
1110  PLyObToDatum *base = arg->u.domain.base;
1111 
1112  result = base->func(base, plrv, isnull, inarray);
1113  domain_check(result, *isnull, arg->typoid,
1114  &arg->u.domain.domain_info, arg->mcxt);
1115  return result;
1116 }
1117 
1118 
1119 /*
1120  * Convert using a to-SQL transform function.
1121  */
1122 static Datum
1124  bool *isnull, bool inarray)
1125 {
1126  if (plrv == Py_None)
1127  {
1128  *isnull = true;
1129  return (Datum) 0;
1130  }
1131  *isnull = false;
1132  return FunctionCall1(&arg->u.transform.typtransform, PointerGetDatum(plrv));
1133 }
1134 
1135 
1136 /*
1137  * Convert Python sequence to SQL array.
1138  */
1139 static Datum
1141  bool *isnull, bool inarray)
1142 {
1143  ArrayType *array;
1144  int i;
1145  Datum *elems;
1146  bool *nulls;
1147  int64 len;
1148  int ndim;
1149  int dims[MAXDIM];
1150  int lbs[MAXDIM];
1151  int currelem;
1152  PyObject *pyptr = plrv;
1153  PyObject *next;
1154 
1155  if (plrv == Py_None)
1156  {
1157  *isnull = true;
1158  return (Datum) 0;
1159  }
1160  *isnull = false;
1161 
1162  /*
1163  * Determine the number of dimensions, and their sizes.
1164  */
1165  ndim = 0;
1166  len = 1;
1167 
1168  Py_INCREF(plrv);
1169 
1170  for (;;)
1171  {
1172  if (!PyList_Check(pyptr))
1173  break;
1174 
1175  if (ndim == MAXDIM)
1176  PLy_elog(ERROR, "number of array dimensions exceeds the maximum allowed (%d)", MAXDIM);
1177 
1178  dims[ndim] = PySequence_Length(pyptr);
1179  if (dims[ndim] < 0)
1180  PLy_elog(ERROR, "could not determine sequence length for function return value");
1181 
1182  if (dims[ndim] > MaxAllocSize)
1183  PLy_elog(ERROR, "array size exceeds the maximum allowed");
1184 
1185  len *= dims[ndim];
1186  if (len > MaxAllocSize)
1187  PLy_elog(ERROR, "array size exceeds the maximum allowed");
1188 
1189  if (dims[ndim] == 0)
1190  {
1191  /* empty sequence */
1192  break;
1193  }
1194 
1195  ndim++;
1196 
1197  next = PySequence_GetItem(pyptr, 0);
1198  Py_XDECREF(pyptr);
1199  pyptr = next;
1200  }
1201  Py_XDECREF(pyptr);
1202 
1203  /*
1204  * Check for zero dimensions. This happens if the object is a tuple or a
1205  * string, rather than a list, or is not a sequence at all. We don't map
1206  * tuples or strings to arrays in general, but in the first level, be
1207  * lenient, for historical reasons. So if the object is a sequence of any
1208  * kind, treat it as a one-dimensional array.
1209  */
1210  if (ndim == 0)
1211  {
1212  if (!PySequence_Check(plrv))
1213  PLy_elog(ERROR, "return value of function with array return type is not a Python sequence");
1214 
1215  ndim = 1;
1216  len = dims[0] = PySequence_Length(plrv);
1217  }
1218 
1219  /*
1220  * Traverse the Python lists, in depth-first order, and collect all the
1221  * elements at the bottom level into 'elems'/'nulls' arrays.
1222  */
1223  elems = palloc(sizeof(Datum) * len);
1224  nulls = palloc(sizeof(bool) * len);
1225  currelem = 0;
1227  dims, ndim, 0,
1228  elems, nulls, &currelem);
1229 
1230  for (i = 0; i < ndim; i++)
1231  lbs[i] = 1;
1232 
1233  array = construct_md_array(elems,
1234  nulls,
1235  ndim,
1236  dims,
1237  lbs,
1238  arg->u.array.elmbasetype,
1239  arg->u.array.elm->typlen,
1240  arg->u.array.elm->typbyval,
1241  arg->u.array.elm->typalign);
1242 
1243  return PointerGetDatum(array);
1244 }
1245 
1246 /*
1247  * Helper function for PLySequence_ToArray. Traverse a Python list of lists in
1248  * depth-first order, storing the elements in 'elems'.
1249  */
1250 static void
1252  int *dims, int ndim, int dim,
1253  Datum *elems, bool *nulls, int *currelem)
1254 {
1255  int i;
1256 
1257  if (PySequence_Length(list) != dims[dim])
1258  ereport(ERROR,
1259  (errmsg("wrong length of inner sequence: has length %d, but %d was expected",
1260  (int) PySequence_Length(list), dims[dim]),
1261  (errdetail("To construct a multidimensional array, the inner sequences must all have the same length."))));
1262 
1263  if (dim < ndim - 1)
1264  {
1265  for (i = 0; i < dims[dim]; i++)
1266  {
1267  PyObject *sublist = PySequence_GetItem(list, i);
1268 
1269  PLySequence_ToArray_recurse(elm, sublist, dims, ndim, dim + 1,
1270  elems, nulls, currelem);
1271  Py_XDECREF(sublist);
1272  }
1273  }
1274  else
1275  {
1276  for (i = 0; i < dims[dim]; i++)
1277  {
1278  PyObject *obj = PySequence_GetItem(list, i);
1279 
1280  elems[*currelem] = elm->func(elm, obj, &nulls[*currelem], true);
1281  Py_XDECREF(obj);
1282  (*currelem)++;
1283  }
1284  }
1285 }
1286 
1287 
1288 /*
1289  * Convert a Python string to composite, using record_in.
1290  */
1291 static Datum
1292 PLyString_ToComposite(PLyObToDatum *arg, PyObject *string, bool inarray)
1293 {
1294  char *str;
1295 
1296  /*
1297  * Set up call data for record_in, if we didn't already. (We can't just
1298  * use DirectFunctionCall, because record_in needs a fn_extra field.)
1299  */
1300  if (!OidIsValid(arg->u.tuple.recinfunc.fn_oid))
1301  fmgr_info_cxt(F_RECORD_IN, &arg->u.tuple.recinfunc, arg->mcxt);
1302 
1303  str = PLyObject_AsString(string);
1304 
1305  /*
1306  * If we are parsing a composite type within an array, and the string
1307  * isn't a valid record literal, there's a high chance that the function
1308  * did something like:
1309  *
1310  * CREATE FUNCTION .. RETURNS comptype[] AS $$ return [['foo', 'bar']] $$
1311  * LANGUAGE plpython;
1312  *
1313  * Before PostgreSQL 10, that was interpreted as a single-dimensional
1314  * array, containing record ('foo', 'bar'). PostgreSQL 10 added support
1315  * for multi-dimensional arrays, and it is now interpreted as a
1316  * two-dimensional array, containing two records, 'foo', and 'bar'.
1317  * record_in() will throw an error, because "foo" is not a valid record
1318  * literal.
1319  *
1320  * To make that less confusing to users who are upgrading from older
1321  * versions, try to give a hint in the typical instances of that. If we
1322  * are parsing an array of composite types, and we see a string literal
1323  * that is not a valid record literal, give a hint. We only want to give
1324  * the hint in the narrow case of a malformed string literal, not any
1325  * error from record_in(), so check for that case here specifically.
1326  *
1327  * This check better match the one in record_in(), so that we don't forbid
1328  * literals that are actually valid!
1329  */
1330  if (inarray)
1331  {
1332  char *ptr = str;
1333 
1334  /* Allow leading whitespace */
1335  while (*ptr && isspace((unsigned char) *ptr))
1336  ptr++;
1337  if (*ptr++ != '(')
1338  ereport(ERROR,
1339  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1340  errmsg("malformed record literal: \"%s\"", str),
1341  errdetail("Missing left parenthesis."),
1342  errhint("To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".")));
1343  }
1344 
1345  return InputFunctionCall(&arg->u.tuple.recinfunc,
1346  str,
1347  arg->typoid,
1348  arg->typmod);
1349 }
1350 
1351 
1352 static Datum
1354 {
1355  Datum result;
1356  HeapTuple tuple;
1357  Datum *values;
1358  bool *nulls;
1359  volatile int i;
1360 
1361  Assert(PyMapping_Check(mapping));
1362 
1363  /* Build tuple */
1364  values = palloc(sizeof(Datum) * desc->natts);
1365  nulls = palloc(sizeof(bool) * desc->natts);
1366  for (i = 0; i < desc->natts; ++i)
1367  {
1368  char *key;
1369  PyObject *volatile value;
1370  PLyObToDatum *att;
1371  Form_pg_attribute attr = TupleDescAttr(desc, i);
1372 
1373  if (attr->attisdropped)
1374  {
1375  values[i] = (Datum) 0;
1376  nulls[i] = true;
1377  continue;
1378  }
1379 
1380  key = NameStr(attr->attname);
1381  value = NULL;
1382  att = &arg->u.tuple.atts[i];
1383  PG_TRY();
1384  {
1385  value = PyMapping_GetItemString(mapping, key);
1386  if (!value)
1387  ereport(ERROR,
1388  (errcode(ERRCODE_UNDEFINED_COLUMN),
1389  errmsg("key \"%s\" not found in mapping", key),
1390  errhint("To return null in a column, "
1391  "add the value None to the mapping with the key named after the column.")));
1392 
1393  values[i] = att->func(att, value, &nulls[i], false);
1394 
1395  Py_XDECREF(value);
1396  value = NULL;
1397  }
1398  PG_CATCH();
1399  {
1400  Py_XDECREF(value);
1401  PG_RE_THROW();
1402  }
1403  PG_END_TRY();
1404  }
1405 
1406  tuple = heap_form_tuple(desc, values, nulls);
1407  result = heap_copy_tuple_as_datum(tuple, desc);
1408  heap_freetuple(tuple);
1409 
1410  pfree(values);
1411  pfree(nulls);
1412 
1413  return result;
1414 }
1415 
1416 
1417 static Datum
1419 {
1420  Datum result;
1421  HeapTuple tuple;
1422  Datum *values;
1423  bool *nulls;
1424  volatile int idx;
1425  volatile int i;
1426 
1427  Assert(PySequence_Check(sequence));
1428 
1429  /*
1430  * Check that sequence length is exactly same as PG tuple's. We actually
1431  * can ignore exceeding items or assume missing ones as null but to avoid
1432  * plpython developer's errors we are strict here
1433  */
1434  idx = 0;
1435  for (i = 0; i < desc->natts; i++)
1436  {
1437  if (!TupleDescAttr(desc, i)->attisdropped)
1438  idx++;
1439  }
1440  if (PySequence_Length(sequence) != idx)
1441  ereport(ERROR,
1442  (errcode(ERRCODE_DATATYPE_MISMATCH),
1443  errmsg("length of returned sequence did not match number of columns in row")));
1444 
1445  /* Build tuple */
1446  values = palloc(sizeof(Datum) * desc->natts);
1447  nulls = palloc(sizeof(bool) * desc->natts);
1448  idx = 0;
1449  for (i = 0; i < desc->natts; ++i)
1450  {
1451  PyObject *volatile value;
1452  PLyObToDatum *att;
1453 
1454  if (TupleDescAttr(desc, i)->attisdropped)
1455  {
1456  values[i] = (Datum) 0;
1457  nulls[i] = true;
1458  continue;
1459  }
1460 
1461  value = NULL;
1462  att = &arg->u.tuple.atts[i];
1463  PG_TRY();
1464  {
1465  value = PySequence_GetItem(sequence, idx);
1466  Assert(value);
1467 
1468  values[i] = att->func(att, value, &nulls[i], false);
1469 
1470  Py_XDECREF(value);
1471  value = NULL;
1472  }
1473  PG_CATCH();
1474  {
1475  Py_XDECREF(value);
1476  PG_RE_THROW();
1477  }
1478  PG_END_TRY();
1479 
1480  idx++;
1481  }
1482 
1483  tuple = heap_form_tuple(desc, values, nulls);
1484  result = heap_copy_tuple_as_datum(tuple, desc);
1485  heap_freetuple(tuple);
1486 
1487  pfree(values);
1488  pfree(nulls);
1489 
1490  return result;
1491 }
1492 
1493 
1494 static Datum
1495 PLyGenericObject_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *object, bool inarray)
1496 {
1497  Datum result;
1498  HeapTuple tuple;
1499  Datum *values;
1500  bool *nulls;
1501  volatile int i;
1502 
1503  /* Build tuple */
1504  values = palloc(sizeof(Datum) * desc->natts);
1505  nulls = palloc(sizeof(bool) * desc->natts);
1506  for (i = 0; i < desc->natts; ++i)
1507  {
1508  char *key;
1509  PyObject *volatile value;
1510  PLyObToDatum *att;
1511  Form_pg_attribute attr = TupleDescAttr(desc, i);
1512 
1513  if (attr->attisdropped)
1514  {
1515  values[i] = (Datum) 0;
1516  nulls[i] = true;
1517  continue;
1518  }
1519 
1520  key = NameStr(attr->attname);
1521  value = NULL;
1522  att = &arg->u.tuple.atts[i];
1523  PG_TRY();
1524  {
1525  value = PyObject_GetAttrString(object, key);
1526  if (!value)
1527  {
1528  /*
1529  * No attribute for this column in the object.
1530  *
1531  * If we are parsing a composite type in an array, a likely
1532  * cause is that the function contained something like "[[123,
1533  * 'foo']]". Before PostgreSQL 10, that was interpreted as an
1534  * array, with a composite type (123, 'foo') in it. But now
1535  * it's interpreted as a two-dimensional array, and we try to
1536  * interpret "123" as the composite type. See also similar
1537  * heuristic in PLyObject_ToScalar().
1538  */
1539  ereport(ERROR,
1540  (errcode(ERRCODE_UNDEFINED_COLUMN),
1541  errmsg("attribute \"%s\" does not exist in Python object", key),
1542  inarray ?
1543  errhint("To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".") :
1544  errhint("To return null in a column, let the returned object have an attribute named after column with value None.")));
1545  }
1546 
1547  values[i] = att->func(att, value, &nulls[i], false);
1548 
1549  Py_XDECREF(value);
1550  value = NULL;
1551  }
1552  PG_CATCH();
1553  {
1554  Py_XDECREF(value);
1555  PG_RE_THROW();
1556  }
1557  PG_END_TRY();
1558  }
1559 
1560  tuple = heap_form_tuple(desc, values, nulls);
1561  result = heap_copy_tuple_as_datum(tuple, desc);
1562  heap_freetuple(tuple);
1563 
1564  pfree(values);
1565  pfree(nulls);
1566 
1567  return result;
1568 }
void * domain_info
Definition: plpy_typeio.h:121
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1876
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:619
TupleDesc recdesc
Definition: plpy_typeio.h:42
static PyObject * PLyInt_FromInt32(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:613
Oid tdtypeid
Definition: tupdesc.h:83
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
Definition: plpy_typeio.c:123
int errhint(const char *fmt,...)
Definition: elog.c:987
PLyDatumToOb * atts
Definition: plpy_typeio.h:47
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2650
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
#define VARDATA(PTR)
Definition: postgres.h:302
static int32 next
Definition: blutils.c:211
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:144
PyObject * PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc)
Definition: plpy_typeio.c:137
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1641
FmgrInfo typfunc
Definition: plpy_typeio.h:31
#define DatumGetInt32(X)
Definition: postgres.h:457
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:553
#define MAXDIM
Definition: c.h:496
#define PyObject_Bytes
Definition: plpython.h:87
FmgrInfo typfunc
Definition: plpy_typeio.h:94
#define PointerGetDatum(X)
Definition: postgres.h:541
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
uint64 tupdescid
Definition: plpy_typeio.h:45
#define VARHDRSZ
Definition: c.h:522
union PLyDatumToOb::@151 u
#define DatumGetObjectId(X)
Definition: postgres.h:485
char * pstrdup(const char *in)
Definition: mcxt.c:1161
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:652
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
TypeCacheEntry * typentry
Definition: plpy_typeio.h:44
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PyBytes_FromStringAndSize
Definition: plpython.h:85
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
#define DatumGetByteaPP(X)
Definition: fmgr.h:260
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:414
int16 typlen
Definition: typcache.h:37
#define PyBytes_AsString
Definition: plpython.h:84
#define OidIsValid(objectId)
Definition: c.h:605
bool typbyval
Definition: typcache.h:38
PLyObToTransform transform
Definition: plpy_typeio.h:144
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:145
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:264
PLyObToDatum * base
Definition: plpy_typeio.h:120
int natts
Definition: tupdesc.h:82
PLyObToDatumFunc func
Definition: plpy_typeio.h:131
int32 tdtypmod
Definition: tupdesc.h:84
static PyObject * PLyString_FromScalar(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:645
FmgrInfo typtransform
Definition: plpy_typeio.h:53
signed int int32
Definition: c.h:313
PLyObToDomain domain
Definition: plpy_typeio.h:143
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:784
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1753
HeapTupleHeader t_data
Definition: htup.h:68
Oid domainBaseType
Definition: typcache.h:104
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:467
static Datum PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1081
static PyObject * PLyInt_FromInt16(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:607
PLyArrayToOb array
Definition: plpy_typeio.h:68
PLyObToArray array
Definition: plpy_typeio.h:141
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
TupleDesc recdesc
Definition: plpy_typeio.h:107
static PyObject * decimal_constructor
#define DatumGetCString(X)
Definition: postgres.h:551
void PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:264
static PyObject * PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:567
char * PLyObject_AsString(PyObject *plrv)
Definition: plpy_typeio.c:1023
#define ARR_DIMS(a)
Definition: array.h:279
PLyDatumToObFunc func
Definition: plpy_typeio.h:58
PLyTransformToOb transform
Definition: plpy_typeio.h:70
#define PLy_elog
#define DatumGetInt64(X)
Definition: postgres.h:592
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1109
static PyObject * PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:561
uint64 tupdescid
Definition: plpy_typeio.h:110
uint32 t_len
Definition: htup.h:64
#define ARR_DATA_PTR(a)
Definition: array.h:307
PLyObToScalar scalar
Definition: plpy_typeio.h:140
static PyObject * PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:631
void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:168
void check_stack_depth(void)
Definition: postgres.c:3159
static Datum PLyObject_ToDomain(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1106
int32 typmod
Definition: plpy_typeio.h:60
static Datum PLyObject_ToBool(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:875
int errdetail(const char *fmt,...)
Definition: elog.c:873
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:421
#define DatumGetInt16(X)
Definition: postgres.h:429
#define DatumGetBool(X)
Definition: postgres.h:378
int32 domainBaseTypmod
Definition: typcache.h:105
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
FmgrInfo typtransform
Definition: plpy_typeio.h:126
int16 typlen
Definition: plpy_typeio.h:62
static Datum PLyGenericObject_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *object, bool inarray)
Definition: plpy_typeio.c:1495
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:134
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:172
#define ereport(elevel, rest)
Definition: elog.h:122
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2617
static PyObject * PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:573
union PLyObToDatum::@152 u
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:1038
PLyDatumToOb * elm
Definition: plpy_typeio.h:36
static Datum PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:940
#define PyBytes_Size
Definition: plpython.h:86
#define TYPECACHE_DOMAIN_BASE_INFO
Definition: typcache.h:139
#define MaxAllocSize
Definition: memutils.h:40
TypeCacheEntry * typentry
Definition: plpy_typeio.h:109
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:781
uint8 bits8
Definition: c.h:332
#define DatumGetFloat8(X)
Definition: postgres.h:713
uintptr_t Datum
Definition: postgres.h:367
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:457
static struct @131 value
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
Definition: domains.c:327
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:218
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:814
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1709
#define BoolGetDatum(X)
Definition: postgres.h:387
static Datum PLyString_ToComposite(PLyObToDatum *arg, PyObject *string, bool inarray)
Definition: plpy_typeio.c:1292
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:321
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
#define PG_CATCH()
Definition: elog.h:293
char typtype
Definition: typcache.h:41
PyObject * PLy_input_convert(PLyDatumToOb *arg, Datum val)
Definition: plpy_typeio.c:84
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:670
#define Assert(condition)
Definition: c.h:699
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:625
#define DatumGetFloat4(X)
Definition: postgres.h:665
PLyObToDatum * elm
Definition: plpy_typeio.h:100
MemoryContext mcxt
Definition: plpy_typeio.h:137
PLyScalarToOb scalar
Definition: plpy_typeio.h:67
uint64 tupDesc_identifier
Definition: typcache.h:86
#define PG_RE_THROW()
Definition: elog.h:314
#define ARR_NDIM(a)
Definition: array.h:275
PyObject * PLyUnicode_Bytes(PyObject *unicode)
Definition: plpy_util.c:25
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
Definition: lsyscache.c:1897
static Datum PLyObject_ToTransform(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1123
#define DatumGetPointer(X)
Definition: postgres.h:534
#define PinTupleDesc(tupdesc)
Definition: tupdesc.h:118
static Datum values[MAXATTR]
Definition: bootstrap.c:164
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:299
static PyObject * PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
Definition: plpy_typeio.c:658
PLyObToTuple tuple
Definition: plpy_typeio.h:142
char typalign
Definition: typcache.h:39
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:71
static Datum PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:1140
int i
#define FunctionCall1(flinfo, arg1)
Definition: fmgr.h:608
#define NameStr(name)
Definition: c.h:576
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:710
void * arg
PLyObToDatum * atts
Definition: plpy_typeio.h:112
Definition: c.h:516
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1866
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
MemoryContext mcxt
Definition: plpy_typeio.h:64
#define elog
Definition: elog.h:219
static Datum PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
Definition: plpy_typeio.c:893
static Datum PLySequence_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *sequence)
Definition: plpy_typeio.c:1418
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:3314
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:124
#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:1251
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2275
PLyTupleToOb tuple
Definition: plpy_typeio.h:69
static Datum PLyMapping_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *mapping)
Definition: plpy_typeio.c:1353
TupleDesc tupDesc
Definition: typcache.h:85
static PyObject * PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc)
Definition: plpy_typeio.c:818
FmgrInfo recinfunc
Definition: plpy_typeio.h:115
#define ARR_NULLBITMAP(a)
Definition: array.h:285
long val
Definition: informix.c:689
#define PG_END_TRY()
Definition: elog.h:300
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
Definition: plpy_main.c:423
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:451
#define DatumGetArrayTypeP(X)
Definition: array.h:246