Oliver Jowett wrote:

Perhaps PerformCursorOpen should copy the query tree before planning, or plan in a different memory context?

Patch attached. It moves query planning inside the new portal's memory context. With this applied I can run Barry's testcase without errors, and valgrind seems OK with it too.


-O
Index: src/backend/commands/portalcmds.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/portalcmds.c,v
retrieving revision 1.36
diff -c -r1.36 portalcmds.c
*** src/backend/commands/portalcmds.c   16 Sep 2004 16:58:28 -0000      1.36
--- src/backend/commands/portalcmds.c   24 Nov 2004 09:28:34 -0000
***************
*** 67,73 ****
         * query, so we are not expecting rule rewriting to do anything
         * strange.
         */
!       rewritten = QueryRewrite((Query *) stmt->query);
        if (list_length(rewritten) != 1 || !IsA(linitial(rewritten), Query))
                elog(ERROR, "unexpected rewrite result");
        query = (Query *) linitial(rewritten);
--- 67,86 ----
         * query, so we are not expecting rule rewriting to do anything
         * strange.
         */
! 
!       /* Create a new portal, and do all query planning on a copy of
!        * the query allocated in the new portal's memory context. The
!        * planner may modify the query, and it is not safe to have
!        * those modifications persist as we are ourselves running in a
!        * transient portal context.
!        */
!       portal = CreatePortal(stmt->portalname, false, false);
! 
!       oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
! 
!       query = copyObject(stmt->query);
! 
!       rewritten = QueryRewrite(query);
        if (list_length(rewritten) != 1 || !IsA(linitial(rewritten), Query))
                elog(ERROR, "unexpected rewrite result");
        query = (Query *) linitial(rewritten);
***************
*** 86,102 ****
  
        plan = planner(query, true, stmt->options, NULL);
  
-       /*
-        * Create a portal and copy the query and plan into its memory
-        * context.
-        */
-       portal = CreatePortal(stmt->portalname, false, false);
- 
-       oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
- 
-       query = copyObject(query);
-       plan = copyObject(plan);
- 
        PortalDefineQuery(portal,
                                          NULL,         /* unfortunately don't 
have sourceText */
                                          "SELECT", /* cursor's query is always 
a SELECT */
--- 99,104 ----
---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
      joining column's datatypes do not match

Reply via email to