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

Commitb05186f

Browse files
committed
Invalidate PL/Python functions with composite type argument when the
type changes.The invalidation will cause the type information to be refetched, andeverything will work.Jan Urbański, reviewed by Alex Hunsaker
1 parent964b46d commitb05186f

File tree

4 files changed

+223
-2
lines changed

4 files changed

+223
-2
lines changed

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,58 @@ SELECT * FROM test_type_conversion_array_error();
603603
ERROR: return value of function with array return type is not a Python sequence
604604
CONTEXT: while creating return value
605605
PL/Python function "test_type_conversion_array_error"
606+
---
607+
--- Composite types
608+
---
609+
CREATE TABLE employee (
610+
name text,
611+
basesalary integer,
612+
bonus integer
613+
);
614+
INSERT INTO employee VALUES ('John', 100, 10), ('Mary', 200, 10);
615+
CREATE OR REPLACE FUNCTION test_composite_table_input(e employee) RETURNS integer AS $$
616+
return e['basesalary'] + e['bonus']
617+
$$ LANGUAGE plpythonu;
618+
SELECT name, test_composite_table_input(employee.*) FROM employee;
619+
name | test_composite_table_input
620+
------+----------------------------
621+
John | 110
622+
Mary | 210
623+
(2 rows)
624+
625+
ALTER TABLE employee DROP bonus;
626+
SELECT name, test_composite_table_input(employee.*) FROM employee;
627+
ERROR: KeyError: 'bonus'
628+
CONTEXT: PL/Python function "test_composite_table_input"
629+
ALTER TABLE employee ADD bonus integer;
630+
UPDATE employee SET bonus = 10;
631+
SELECT name, test_composite_table_input(employee.*) FROM employee;
632+
name | test_composite_table_input
633+
------+----------------------------
634+
John | 110
635+
Mary | 210
636+
(2 rows)
637+
638+
CREATE TYPE named_pair AS (
639+
i integer,
640+
j integer
641+
);
642+
CREATE OR REPLACE FUNCTION test_composite_type_input(p named_pair) RETURNS integer AS $$
643+
return sum(p.values())
644+
$$ LANGUAGE plpythonu;
645+
SELECT test_composite_type_input(row(1, 2));
646+
test_composite_type_input
647+
---------------------------
648+
3
649+
(1 row)
650+
651+
ALTER TYPE named_pair RENAME TO named_pair_2;
652+
SELECT test_composite_type_input(row(1, 2));
653+
test_composite_type_input
654+
---------------------------
655+
3
656+
(1 row)
657+
606658
--
607659
-- Prepared statements
608660
--

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,58 @@ SELECT * FROM test_type_conversion_array_error();
603603
ERROR: return value of function with array return type is not a Python sequence
604604
CONTEXT: while creating return value
605605
PL/Python function "test_type_conversion_array_error"
606+
---
607+
--- Composite types
608+
---
609+
CREATE TABLE employee (
610+
name text,
611+
basesalary integer,
612+
bonus integer
613+
);
614+
INSERT INTO employee VALUES ('John', 100, 10), ('Mary', 200, 10);
615+
CREATE OR REPLACE FUNCTION test_composite_table_input(e employee) RETURNS integer AS $$
616+
return e['basesalary'] + e['bonus']
617+
$$ LANGUAGE plpython3u;
618+
SELECT name, test_composite_table_input(employee.*) FROM employee;
619+
name | test_composite_table_input
620+
------+----------------------------
621+
John | 110
622+
Mary | 210
623+
(2 rows)
624+
625+
ALTER TABLE employee DROP bonus;
626+
SELECT name, test_composite_table_input(employee.*) FROM employee;
627+
ERROR: KeyError: 'bonus'
628+
CONTEXT: PL/Python function "test_composite_table_input"
629+
ALTER TABLE employee ADD bonus integer;
630+
UPDATE employee SET bonus = 10;
631+
SELECT name, test_composite_table_input(employee.*) FROM employee;
632+
name | test_composite_table_input
633+
------+----------------------------
634+
John | 110
635+
Mary | 210
636+
(2 rows)
637+
638+
CREATE TYPE named_pair AS (
639+
i integer,
640+
j integer
641+
);
642+
CREATE OR REPLACE FUNCTION test_composite_type_input(p named_pair) RETURNS integer AS $$
643+
return sum(p.values())
644+
$$ LANGUAGE plpython3u;
645+
SELECT test_composite_type_input(row(1, 2));
646+
test_composite_type_input
647+
---------------------------
648+
3
649+
(1 row)
650+
651+
ALTER TYPE named_pair RENAME TO named_pair_2;
652+
SELECT test_composite_type_input(row(1, 2));
653+
test_composite_type_input
654+
---------------------------
655+
3
656+
(1 row)
657+
606658
--
607659
-- Prepared statements
608660
--

‎src/pl/plpython/plpython.c

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ typedef int Py_ssize_t;
101101
#include"nodes/makefuncs.h"
102102
#include"parser/parse_type.h"
103103
#include"tcop/tcopprot.h"
104+
#include"access/transam.h"
104105
#include"access/xact.h"
105106
#include"utils/builtins.h"
106107
#include"utils/hsearch.h"
@@ -195,6 +196,10 @@ typedef struct PLyTypeInfo
195196
* datatype; 1 = rowtype; 2 = rowtype, but I/O functions not set up yet
196197
*/
197198
intis_rowtype;
199+
/* used to check if the type has been modified */
200+
Oidtyp_relid;
201+
TransactionIdtyprel_xmin;
202+
ItemPointerDatatyprel_tid;
198203
}PLyTypeInfo;
199204

200205

@@ -1335,11 +1340,50 @@ PLy_function_delete_args(PLyProcedure *proc)
13351340
staticbool
13361341
PLy_procedure_valid(PLyProcedure*proc,HeapTupleprocTup)
13371342
{
1343+
inti;
1344+
boolvalid;
1345+
13381346
Assert(proc!=NULL);
13391347

13401348
/* If the pg_proc tuple has changed, it's not valid */
1341-
return (proc->fn_xmin==HeapTupleHeaderGetXmin(procTup->t_data)&&
1342-
ItemPointerEquals(&proc->fn_tid,&procTup->t_self));
1349+
if (!(proc->fn_xmin==HeapTupleHeaderGetXmin(procTup->t_data)&&
1350+
ItemPointerEquals(&proc->fn_tid,&procTup->t_self)))
1351+
return false;
1352+
1353+
valid= true;
1354+
/* If there are composite input arguments, they might have changed */
1355+
for (i=0;i<proc->nargs;i++)
1356+
{
1357+
Oidrelid;
1358+
HeapTuplerelTup;
1359+
1360+
/* Short-circuit on first changed argument */
1361+
if (!valid)
1362+
break;
1363+
1364+
/* Only check input arguments that are composite */
1365+
if (proc->args[i].is_rowtype!=1)
1366+
continue;
1367+
1368+
Assert(OidIsValid(proc->args[i].typ_relid));
1369+
Assert(TransactionIdIsValid(proc->args[i].typrel_xmin));
1370+
Assert(ItemPointerIsValid(&proc->args[i].typrel_tid));
1371+
1372+
/* Get the pg_class tuple for the argument type */
1373+
relid=proc->args[i].typ_relid;
1374+
relTup=SearchSysCache1(RELOID,ObjectIdGetDatum(relid));
1375+
if (!HeapTupleIsValid(relTup))
1376+
elog(ERROR,"cache lookup failed for relation %u",relid);
1377+
1378+
/* If it has changed, the function is not valid */
1379+
if (!(proc->args[i].typrel_xmin==HeapTupleHeaderGetXmin(relTup->t_data)&&
1380+
ItemPointerEquals(&proc->args[i].typrel_tid,&relTup->t_self)))
1381+
valid= false;
1382+
1383+
ReleaseSysCache(relTup);
1384+
}
1385+
1386+
returnvalid;
13431387
}
13441388

13451389

@@ -1747,6 +1791,33 @@ PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
17471791
arg->in.r.atts=PLy_malloc0(desc->natts*sizeof(PLyDatumToOb));
17481792
}
17491793

1794+
/* Can this be an unnamed tuple? If not, then an Assert would be enough */
1795+
if (desc->tdtypmod!=-1)
1796+
elog(ERROR,"received unnamed record type as input");
1797+
1798+
Assert(OidIsValid(desc->tdtypeid));
1799+
1800+
/*
1801+
* RECORDOID means we got called to create input functions for a tuple
1802+
* fetched by plpy.execute or for an anonymous record type
1803+
*/
1804+
if (desc->tdtypeid!=RECORDOID&& !TransactionIdIsValid(arg->typrel_xmin))
1805+
{
1806+
HeapTuplerelTup;
1807+
1808+
/* Get the pg_class tuple corresponding to the type of the input */
1809+
arg->typ_relid=typeidTypeRelid(desc->tdtypeid);
1810+
relTup=SearchSysCache1(RELOID,ObjectIdGetDatum(arg->typ_relid));
1811+
if (!HeapTupleIsValid(relTup))
1812+
elog(ERROR,"cache lookup failed for relation %u",arg->typ_relid);
1813+
1814+
/* Extract the XMIN value to later use it in PLy_procedure_valid */
1815+
arg->typrel_xmin=HeapTupleHeaderGetXmin(relTup->t_data);
1816+
arg->typrel_tid=relTup->t_self;
1817+
1818+
ReleaseSysCache(relTup);
1819+
}
1820+
17501821
for (i=0;i<desc->natts;i++)
17511822
{
17521823
HeapTupletypeTup;
@@ -1951,6 +2022,9 @@ PLy_typeinfo_init(PLyTypeInfo *arg)
19512022
arg->in.r.natts=arg->out.r.natts=0;
19522023
arg->in.r.atts=NULL;
19532024
arg->out.r.atts=NULL;
2025+
arg->typ_relid=InvalidOid;
2026+
arg->typrel_xmin=InvalidTransactionId;
2027+
ItemPointerSetInvalid(&arg->typrel_tid);
19542028
}
19552029

19562030
staticvoid

‎src/pl/plpython/sql/plpython_types.sql

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,49 @@ $$ LANGUAGE plpythonu;
279279
SELECT*FROM test_type_conversion_array_error();
280280

281281

282+
---
283+
--- Composite types
284+
---
285+
286+
CREATETABLEemployee (
287+
nametext,
288+
basesalaryinteger,
289+
bonusinteger
290+
);
291+
292+
INSERT INTO employeeVALUES ('John',100,10), ('Mary',200,10);
293+
294+
CREATE OR REPLACEFUNCTIONtest_composite_table_input(e employee) RETURNSintegerAS $$
295+
return e['basesalary']+ e['bonus']
296+
$$ LANGUAGE plpythonu;
297+
298+
SELECT name, test_composite_table_input(employee.*)FROM employee;
299+
300+
ALTERTABLE employee DROP bonus;
301+
302+
SELECT name, test_composite_table_input(employee.*)FROM employee;
303+
304+
ALTERTABLE employee ADD bonusinteger;
305+
UPDATE employeeSET bonus=10;
306+
307+
SELECT name, test_composite_table_input(employee.*)FROM employee;
308+
309+
CREATETYPEnamed_pairAS (
310+
iinteger,
311+
jinteger
312+
);
313+
314+
CREATE OR REPLACEFUNCTIONtest_composite_type_input(p named_pair) RETURNSintegerAS $$
315+
returnsum(p.values())
316+
$$ LANGUAGE plpythonu;
317+
318+
SELECT test_composite_type_input(row(1,2));
319+
320+
ALTERTYPE named_pair RENAME TO named_pair_2;
321+
322+
SELECT test_composite_type_input(row(1,2));
323+
324+
282325
--
283326
-- Prepared statements
284327
--

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp