Hi.

The following test case makes postgresql backend crash. The trigger is incorrect, but this didn't crash postgresql before

commit 86dc90056dfdbd9d1b891718d2e5614e3e432f35 (HEAD)
Author: Tom Lane <t...@sss.pgh.pa.us>
Date:   Wed Mar 31 11:52:34 2021 -0400

    Rework planning and execution of UPDATE and DELETE.


Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007f1032cc6905 in find_modifytable_subplan (root=0x563f05e61458, plan=0x563f06020e48, rtindex=1, subplan_index=0) at postgres_fdw.c:2373 2373 else if (IsA(subplan, Result) && IsA(outerPlan(subplan), Append))
(gdb) bt
#0 0x00007f1032cc6905 in find_modifytable_subplan (root=0x563f05e61458, plan=0x563f06020e48, rtindex=1, subplan_index=0) at postgres_fdw.c:2373 #1 0x00007f1032cc6a44 in postgresPlanDirectModify (root=0x563f05e61458, plan=0x563f06020e48, resultRelation=1, subplan_index=0) at postgres_fdw.c:2433 #2 0x0000563f035f2876 in make_modifytable (root=0x563f05e61458, subplan=0x563f05e626e8, operation=CMD_DELETE, canSetTag=true, nominalRelation=1, rootRelation=0, partColsUpdated=false, resultRelations=0x563f06020b88, updateColnosLists=0x0, withCheckOptionLists=0x0, returningLists=0x0, rowMarks=0x0, onconflict=0x0, epqParam=0) at createplan.c:7007 #3 0x0000563f035e9ab3 in create_modifytable_plan (root=0x563f05e61458, best_path=0x563f05e62168) at createplan.c:2746 #4 0x0000563f035e5936 in create_plan_recurse (root=0x563f05e61458, best_path=0x563f05e62168, flags=1) at createplan.c:530 #5 0x0000563f035e54be in create_plan (root=0x563f05e61458, best_path=0x563f05e62168) at createplan.c:347 #6 0x0000563f035f8810 in standard_planner (parse=0x563f05e60c08, query_string=0x563f05ffd8d0 "DELETE FROM test_remote WHERE row(i,j)=row(new.i,new.j)", cursorOptions=2048, boundParams=0x563f05e980d8) at planner.c:407 #7 0x0000563f035f84f4 in planner (parse=0x563f05e60c08, query_string=0x563f05ffd8d0 "DELETE FROM test_remote WHERE row(i,j)=row(new.i,new.j)", cursorOptions=2048, boundParams=0x563f05e980d8) at planner.c:271 #8 0x0000563f0373f9c7 in pg_plan_query (querytree=0x563f05e60c08, query_string=0x563f05ffd8d0 "DELETE FROM test_remote WHERE row(i,j)=row(new.i,new.j)", cursorOptions=2048, boundParams=0x563f05e980d8) at postgres.c:847 #9 0x0000563f0373fb15 in pg_plan_queries (querytrees=0x563f05e60bb0, query_string=0x563f05ffd8d0 "DELETE FROM test_remote WHERE row(i,j)=row(new.i,new.j)", cursorOptions=2048, boundParams=0x563f05e980d8) at postgres.c:939 #10 0x0000563f038dade2 in BuildCachedPlan (plansource=0x563f06027590, qlist=0x563f05e60bb0, boundParams=0x563f05e980d8, queryEnv=0x0) at plancache.c:936 #11 0x0000563f038db4d8 in GetCachedPlan (plansource=0x563f06027590, boundParams=0x563f05e980d8, owner=0x563f05f6c478, queryEnv=0x0) at plancache.c:1218 #12 0x0000563f03542235 in _SPI_execute_plan (plan=0x563f060c9ac0, paramLI=0x563f05e980d8, snapshot=0x0, crosscheck_snapshot=0x0, read_only=false, allow_nonatomic=false, fire_triggers=true, tcount=0, caller_dest=0x0, plan_owner=0x563f05f6c478) at spi.c:2405 #13 0x0000563f0353ebb9 in SPI_execute_plan_with_paramlist (plan=0x563f060c9ac0, params=0x563f05e980d8, read_only=false, tcount=0) at spi.c:651 #14 0x00007f1032c2f504 in exec_stmt_execsql (estate=0x7ffcab5c6420, stmt=0x563f05bfb868) at pl_exec.c:4214 #15 0x00007f1032c2a9bc in exec_stmts (estate=0x7ffcab5c6420, stmts=0x563f05bfb8c0) at pl_exec.c:2059 #16 0x00007f1032c2b854 in exec_stmt_if (estate=0x7ffcab5c6420, stmt=0x563f06028700) at pl_exec.c:2481 #17 0x00007f1032c2a842 in exec_stmts (estate=0x7ffcab5c6420, stmts=0x563f06028758) at pl_exec.c:2003 #18 0x00007f1032c2a579 in exec_stmt_block (estate=0x7ffcab5c6420, block=0x563f060288c0) at pl_exec.c:1910 #19 0x00007f1032c29cac in exec_toplevel_block (estate=0x7ffcab5c6420, block=0x563f060288c0) at pl_exec.c:1608 #20 0x00007f1032c28730 in plpgsql_exec_trigger (func=0x563f05f6d940, trigdata=0x7ffcab5c6880) at pl_exec.c:1024 #21 0x00007f1032c43319 in plpgsql_call_handler (fcinfo=0x7ffcab5c6700) at pl_handler.c:268 #22 0x0000563f034a3e2a in ExecCallTriggerFunc (trigdata=0x7ffcab5c6880, tgindx=0, finfo=0x563f05e7aa60, instr=0x0, per_tuple_context=0x563f05c763d0) at trigger.c:2141 #23 0x0000563f034a7674 in AfterTriggerExecute (estate=0x563f05e7a2b0, event=0x563f05e1a580, relInfo=0x563f05e7a738, trigdesc=0x563f05e7a950, finfo=0x563f05e7aa60, instr=0x0, per_tuple_context=0x563f05c763d0, trig_tuple_slot1=0x0, trig_tuple_slot2=0x0) at trigger.c:4034 #24 0x0000563f034a7b8d in afterTriggerInvokeEvents (events=0x563f05f3c540, firing_id=1, estate=0x563f05e7a2b0, delete_ok=false) at trigger.c:4250 #25 0x0000563f034a8353 in AfterTriggerEndQuery (estate=0x563f05e7a2b0) at trigger.c:4587 #26 0x0000563f034dc8eb in standard_ExecutorFinish (queryDesc=0x563f060279a0) at execMain.c:436 #27 0x0000563f034dc7c5 in ExecutorFinish (queryDesc=0x563f060279a0) at execMain.c:404 #28 0x0000563f03745edc in ProcessQuery (plan=0x563f05fc8100, sourceText=0x563f05ad74a0 "DELETE FROM test WHERE i=1;", params=0x0, queryEnv=0x0, dest=0x563f05fc81f0, qc=0x7ffcab5c6cf0) at pquery.c:190 #29 0x0000563f037478fd in PortalRunMulti (portal=0x563f05b3aa50, isTopLevel=true, setHoldSnapshot=false, dest=0x563f05fc81f0, altdest=0x563f05fc81f0, qc=0x7ffcab5c6cf0) at pquery.c:1266 #30 0x0000563f03746e24 in PortalRun (portal=0x563f05b3aa50, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0x563f05fc81f0, altdest=0x563f05fc81f0, qc=0x7ffcab5c6cf0) at pquery.c:786 #31 0x0000563f03740084 in exec_simple_query (query_string=0x563f05ad74a0 "DELETE FROM test WHERE i=1;") at postgres.c:1214 #32 0x0000563f03744c41 in PostgresMain (argc=1, argv=0x7ffcab5c6f10, dbname=0x563f05b02938 "contrib_regression", username=0x563f05b02918 "leoric") at postgres.c:4486 #33 0x0000563f03670f3a in BackendRun (port=0x563f05af8f00) at postmaster.c:4507 #34 0x0000563f036707f3 in BackendStartup (port=0x563f05af8f00) at postmaster.c:4229
#35 0x0000563f0366c97c in ServerLoop () at postmaster.c:1745
#36 0x0000563f0366c115 in PostmasterMain (argc=8, argv=0x563f05ad1820) at postmaster.c:1417 #37 0x0000563f0356193d in main (argc=8, argv=0x563f05ad1820) at main.c:209
(gdb) print *subplan
$2 = {type = T_Result, startup_cost = 0, total_cost = 0, plan_rows = 0, plan_width = 0, parallel_aware = false, parallel_safe = false, async_capable = false, plan_node_id = 0, targetlist = 0x563f06020d40, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0,
  extParam = 0x0, allParam = 0x0}


--
Best regards,
Alexander Pyhalov,
Postgres Professional
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index 911f171d812..7d5051406a2 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -3355,3 +3355,31 @@ CREATE FOREIGN TABLE inv_fsz (c1 int )
 -- Invalid batch_size option
 CREATE FOREIGN TABLE inv_bsz (c1 int )
 	SERVER loopback OPTIONS (batch_size '100$%$#$#');
+
+CREATE TABLE test (i int, j int);
+CREATE TABLE test_base (i int, j int);
+INSERT INTO test VALUES (1,2),(3,4);
+INSERT INTO test_base VALUES (1,2),(3,4);
+CREATE FOREIGN TABLE test_remote (i int, j int)
+       SERVER loopback OPTIONS (table_name 'test_base');
+CREATE FUNCTION update_test()
+RETURNS trigger
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+  rec record;
+  tname text;
+BEGIN
+  IF (TG_OP = 'DELETE') THEN
+  -- reference to new instead of old
+    DELETE FROM test_remote WHERE row(i,j)=row(new.i,new.j);
+  ELSIF (TG_OP = 'INSERT') THEN
+    INSERT INTO test_remote VALUES(new.i, new.j);
+  ELSIF (TG_OP = 'UPDATE') THEN
+    UPDATE test_remote SET i=new.i, j=new.i WHERE i=old.i AND j=old.j;
+  END IF;
+  RETURN NULL;
+  END;
+$function$;
+CREATE TRIGGER tg_upd AFTER INSERT OR DELETE OR UPDATE ON public.test FOR EACH ROW EXECUTE FUNCTION update_test();
+DELETE FROM test WHERE i=1;

Reply via email to