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 *
PLy_input_convert(PLyDatumToOb * arg,Datum val)84 PLy_input_convert(PLyDatumToOb *arg, Datum val)
85 {
86 	PyObject   *result;
87 	PLyExecutionContext *exec_ctx = PLy_current_execution_context();
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
PLy_output_convert(PLyObToDatum * arg,PyObject * val,bool * isnull)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 *
PLy_input_from_tuple(PLyDatumToOb * arg,HeapTuple tuple,TupleDesc desc)137 PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc)
138 {
139 	PyObject   *dict;
140 	PLyExecutionContext *exec_ctx = PLy_current_execution_context();
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
PLy_input_setup_tuple(PLyDatumToOb * arg,TupleDesc desc,PLyProcedure * proc)168 PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc, PLyProcedure *proc)
169 {
170 	int			i;
171 
172 	/* We should be working on a previously-set-up struct */
173 	Assert(arg->func == PLyDict_FromComposite);
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 *)
186 			MemoryContextAllocZero(arg->mcxt,
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
PLy_output_setup_tuple(PLyObToDatum * arg,TupleDesc desc,PLyProcedure * proc)218 PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
219 {
220 	int			i;
221 
222 	/* We should be working on a previously-set-up struct */
223 	Assert(arg->func == PLyObject_ToComposite);
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 *)
236 			MemoryContextAllocZero(arg->mcxt,
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
PLy_output_setup_record(PLyObToDatum * arg,TupleDesc desc,PLyProcedure * proc)264 PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
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
PLy_output_setup_func(PLyObToDatum * arg,MemoryContext arg_mcxt,Oid typeOid,int32 typmod,PLyProcedure * proc)299 PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt,
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 */
309 	check_stack_depth();
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 	{
377 		arg->func = PLyObject_ToTransform;
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 */
383 		arg->func = PLyObject_ToComposite;
384 		/* We'll set up the per-field data later */
385 		arg->u.tuple.recdesc = NULL;
386 		arg->u.tuple.typentry = typentry;
387 		arg->u.tuple.tupdescid = INVALID_TUPLEDESC_IDENTIFIER;
388 		arg->u.tuple.atts = NULL;
389 		arg->u.tuple.natts = 0;
390 		/* Mark this invalid till needed, too */
391 		arg->u.tuple.recinfunc.fn_oid = InvalidOid;
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
PLy_input_setup_func(PLyDatumToOb * arg,MemoryContext arg_mcxt,Oid typeOid,int32 typmod,PLyProcedure * proc)421 PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt,
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 */
432 	check_stack_depth();
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 	{
492 		arg->func = PLyObject_FromTransform;
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 */
498 		arg->func = PLyDict_FromComposite;
499 		/* We'll set up the per-field data later */
500 		arg->u.tuple.recdesc = NULL;
501 		arg->u.tuple.typentry = typentry;
502 		arg->u.tuple.tupdescid = INVALID_TUPLEDESC_IDENTIFIER;
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:
521 				arg->func = PLyDecimal_FromNumeric;
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 *
PLyBool_FromBool(PLyDatumToOb * arg,Datum d)553 PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
554 {
555 	if (DatumGetBool(d))
556 		Py_RETURN_TRUE;
557 	Py_RETURN_FALSE;
558 }
559 
560 static PyObject *
PLyFloat_FromFloat4(PLyDatumToOb * arg,Datum d)561 PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
562 {
563 	return PyFloat_FromDouble(DatumGetFloat4(d));
564 }
565 
566 static PyObject *
PLyFloat_FromFloat8(PLyDatumToOb * arg,Datum d)567 PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
568 {
569 	return PyFloat_FromDouble(DatumGetFloat8(d));
570 }
571 
572 static PyObject *
PLyDecimal_FromNumeric(PLyDatumToOb * arg,Datum d)573 PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
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 
598 	str = DatumGetCString(DirectFunctionCall1(numeric_out, d));
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 *
PLyInt_FromInt16(PLyDatumToOb * arg,Datum d)607 PLyInt_FromInt16(PLyDatumToOb *arg, Datum d)
608 {
609 	return PyInt_FromLong(DatumGetInt16(d));
610 }
611 
612 static PyObject *
PLyInt_FromInt32(PLyDatumToOb * arg,Datum d)613 PLyInt_FromInt32(PLyDatumToOb *arg, Datum d)
614 {
615 	return PyInt_FromLong(DatumGetInt32(d));
616 }
617 
618 static PyObject *
PLyLong_FromInt64(PLyDatumToOb * arg,Datum d)619 PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
620 {
621 	return PyLong_FromLongLong(DatumGetInt64(d));
622 }
623 
624 static PyObject *
PLyLong_FromOid(PLyDatumToOb * arg,Datum d)625 PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
626 {
627 	return PyLong_FromUnsignedLong(DatumGetObjectId(d));
628 }
629 
630 static PyObject *
PLyBytes_FromBytea(PLyDatumToOb * arg,Datum d)631 PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
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 *
PLyString_FromScalar(PLyDatumToOb * arg,Datum d)645 PLyString_FromScalar(PLyDatumToOb *arg, Datum d)
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 *
PLyObject_FromTransform(PLyDatumToOb * arg,Datum d)658 PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
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 *
PLyList_FromArray(PLyDatumToOb * arg,Datum d)670 PLyList_FromArray(PLyDatumToOb *arg, Datum d)
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 *
PLyList_FromArray_recurse(PLyDatumToOb * elm,int * dims,int ndim,int dim,char ** dataptr_p,bits8 ** bitmap_p,int * bitmask_p)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 *
PLyDict_FromComposite(PLyDatumToOb * arg,Datum d)784 PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
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 */
804 	tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
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 *
PLyDict_FromTuple(PLyDatumToOb * arg,HeapTuple tuple,TupleDesc desc)818 PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc)
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
PLyObject_ToBool(PLyObToDatum * arg,PyObject * plrv,bool * isnull,bool inarray)875 PLyObject_ToBool(PLyObToDatum *arg, PyObject *plrv,
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
PLyObject_ToBytea(PLyObToDatum * arg,PyObject * plrv,bool * isnull,bool inarray)893 PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv,
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
PLyObject_ToComposite(PLyObToDatum * arg,PyObject * plrv,bool * isnull,bool inarray)940 PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv,
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);
976 			arg->u.tuple.tupdescid = arg->u.tuple.typentry->tupDesc_identifier;
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 *
PLyObject_AsString(PyObject * plrv)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
PLyObject_ToScalar(PLyObToDatum * arg,PyObject * plrv,bool * isnull,bool inarray)1081 PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv,
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
PLyObject_ToDomain(PLyObToDatum * arg,PyObject * plrv,bool * isnull,bool inarray)1106 PLyObject_ToDomain(PLyObToDatum *arg, PyObject *plrv,
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
PLyObject_ToTransform(PLyObToDatum * arg,PyObject * plrv,bool * isnull,bool inarray)1123 PLyObject_ToTransform(PLyObToDatum *arg, PyObject *plrv,
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
PLySequence_ToArray(PLyObToDatum * arg,PyObject * plrv,bool * isnull,bool inarray)1140 PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv,
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;
1226 	PLySequence_ToArray_recurse(arg->u.array.elm, plrv,
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
PLySequence_ToArray_recurse(PLyObToDatum * elm,PyObject * list,int * dims,int ndim,int dim,Datum * elems,bool * nulls,int * currelem)1251 PLySequence_ToArray_recurse(PLyObToDatum *elm, PyObject *list,
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
PLyString_ToComposite(PLyObToDatum * arg,PyObject * string,bool inarray)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
PLyMapping_ToComposite(PLyObToDatum * arg,TupleDesc desc,PyObject * mapping)1353 PLyMapping_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *mapping)
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
PLySequence_ToComposite(PLyObToDatum * arg,TupleDesc desc,PyObject * sequence)1418 PLySequence_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *sequence)
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
PLyGenericObject_ToComposite(PLyObToDatum * arg,TupleDesc desc,PyObject * object,bool inarray)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 }
1569