Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit157b1e6

Browse files
committed
Fix recursive RECORD-returning plpython functions.
If we recursed to a new call of the same function, with a differentcoldeflist (AS clause), it would fail because the inner call wouldoverwrite the outer call's idea of what to return. This is vaguelylike1d2fe56 andc5bec54, but it's not due to any API decisions:it's just that we computed the actual output rowtype at the start ofthe call, and saved it in the per-procedure data structure. We canfix it at basically zero cost by doing the computation at the endof each call instead of the start.It's not clear that there's any real-world use-case for such afunction, but given that it doesn't cost anything to fix,it'd be silly not to.Per report from Andreas Karlsson. Back-patch to all supportedbranches.Discussion:https://postgr.es/m/1651a46d-3c15-4028-a8c1-d74937b54e19@proxel.se
1 parenta3c00ab commit157b1e6

File tree

3 files changed

+42
-16
lines changed

3 files changed

+42
-16
lines changed

‎src/pl/plpython/expected/plpython_composite.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,20 @@ SELECT * FROM return_record_2('v3') AS (v1 int, v2 int, v3 int);
569569
1 | 2 | 3
570570
(1 row)
571571

572+
-- recursion with a different inner result type didn't use to work
573+
CREATE FUNCTION return_record_3(t text) RETURNS record AS $$
574+
if t == "text":
575+
plpy.execute("SELECT * FROM return_record_3('int') AS (a int)");
576+
return { "a": "x" }
577+
elif t == "int":
578+
return { "a": 1 }
579+
$$ LANGUAGE plpythonu;
580+
SELECT * FROM return_record_3('text') AS (a text);
581+
a
582+
---
583+
x
584+
(1 row)
585+
572586
-- multi-dimensional array of composite types.
573587
CREATE FUNCTION composite_type_as_list() RETURNS type_record[] AS $$
574588
return [[('first', 1), ('second', 1)], [('first', 2), ('second', 2)], [('first', 3), ('second', 3)]];

‎src/pl/plpython/plpy_exec.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,23 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
235235
}
236236
else
237237
{
238-
/* Normal conversion of result */
238+
/*
239+
* Normal conversion of result. However, if the result is of type
240+
* RECORD, we have to set up for that each time through, since it
241+
* might be different from last time.
242+
*/
243+
if (proc->result.typoid==RECORDOID)
244+
{
245+
TupleDescdesc;
246+
247+
if (get_call_result_type(fcinfo,NULL,&desc)!=TYPEFUNC_COMPOSITE)
248+
ereport(ERROR,
249+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
250+
errmsg("function returning record called in context "
251+
"that cannot accept type record")));
252+
PLy_output_setup_record(&proc->result,desc,proc);
253+
}
254+
239255
rv=PLy_output_convert(&proc->result,plrv,
240256
&fcinfo->isnull);
241257
}
@@ -470,21 +486,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
470486
PLy_elog(ERROR,"PyDict_SetItemString() failed, while setting up arguments");
471487
arg=NULL;
472488
}
473-
474-
/* Set up output conversion for functions returning RECORD */
475-
if (proc->result.typoid==RECORDOID)
476-
{
477-
TupleDescdesc;
478-
479-
if (get_call_result_type(fcinfo,NULL,&desc)!=TYPEFUNC_COMPOSITE)
480-
ereport(ERROR,
481-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
482-
errmsg("function returning record called in context "
483-
"that cannot accept type record")));
484-
485-
/* cache the output conversion functions */
486-
PLy_output_setup_record(&proc->result,desc,proc);
487-
}
488489
}
489490
PG_CATCH();
490491
{

‎src/pl/plpython/sql/plpython_composite.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,17 @@ SELECT * FROM return_record_2('v4') AS (v1 int, v3 int, v2 int);
208208
SELECT*FROM return_record_2('v3')AS (v1int, v3int, v2int);
209209
SELECT*FROM return_record_2('v3')AS (v1int, v2int, v3int);
210210

211+
-- recursion with a different inner result type didn't use to work
212+
CREATEFUNCTIONreturn_record_3(ttext) RETURNS recordAS $$
213+
if t=="text":
214+
plpy.execute("SELECT * FROM return_record_3('int') AS (a int)");
215+
return {"a":"x" }
216+
elif t=="int":
217+
return {"a":1 }
218+
$$ LANGUAGE plpythonu;
219+
220+
SELECT*FROM return_record_3('text')AS (atext);
221+
211222
-- multi-dimensional array of composite types.
212223
CREATEFUNCTIONcomposite_type_as_list() RETURNS type_record[]AS $$
213224
return [[('first',1), ('second',1)], [('first',2), ('second',2)], [('first',3), ('second',3)]];

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp