]> granicus.if.org Git - postgresql/commitdiff
Junkfilter logic to force a projection step during SELECT INTO was too
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 2 Mar 2004 18:56:15 +0000 (18:56 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 2 Mar 2004 18:56:15 +0000 (18:56 +0000)
simplistic; it recognized SELECT * FROM but not SELECT * FROM LIMIT.
Per bug report from Jeff Bohmer.

src/backend/executor/execAmi.c
src/backend/executor/execMain.c
src/include/executor/executor.h

index d9a24a344848da8c1d7caeb1fe92627798794da6..8bbd1942eba02fa7a0c7c51be0a02501c28a651c 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.77 2003/12/18 20:21:37 tgl Exp $
+ *     $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.78 2004/03/02 18:56:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -348,3 +348,68 @@ ExecSupportsBackwardScan(Plan *node)
                        return false;
        }
 }
+
+/*
+ * ExecMayReturnRawTuples
+ *             Check whether a plan tree may return "raw" disk tuples (that is,
+ *             pointers to original data in disk buffers, as opposed to temporary
+ *             tuples constructed by projection steps).  In the case of Append,
+ *             some subplans may return raw tuples and others projected tuples;
+ *             we return "true" if any of the returned tuples could be raw.
+ *
+ * This must be passed an already-initialized planstate tree, because we
+ * need to look at the results of ExecAssignScanProjectionInfo().
+ */
+bool
+ExecMayReturnRawTuples(PlanState *node)
+{
+       /*
+        * At a table scan node, we check whether ExecAssignScanProjectionInfo
+        * decided to do projection or not.  Most non-scan nodes always project
+        * and so we can return "false" immediately.  For nodes that don't
+        * project but just pass up input tuples, we have to recursively
+        * examine the input plan node.
+        *
+        * Note: Hash and Material are listed here because they sometimes
+        * return an original input tuple, not a copy.  But Sort and SetOp
+        * never return an original tuple, so they can be treated like
+        * projecting nodes.
+        */
+       switch (nodeTag(node))
+       {
+               /* Table scan nodes */
+               case T_SeqScanState:
+               case T_IndexScanState:
+               case T_TidScanState:
+               case T_SubqueryScanState:
+               case T_FunctionScanState:
+                       if (node->ps_ProjInfo == NULL)
+                               return true;
+                       break;
+
+               /* Non-projecting nodes */
+               case T_HashState:
+               case T_MaterialState:
+               case T_UniqueState:
+               case T_LimitState:
+                       return ExecMayReturnRawTuples(node->lefttree);
+
+               case T_AppendState:
+               {
+                       AppendState *appendstate = (AppendState *) node;
+                       int                     j;
+
+                       for (j = 0; j < appendstate->as_nplans; j++)
+                       {
+                               if (ExecMayReturnRawTuples(appendstate->appendplans[j]))
+                                       return true;
+                       }
+                       break;
+               }
+
+               /* All projecting node types come here */
+               default:
+                       break;
+       }
+       return false;
+}
index 4f36602aa048ffb4f656df80b902f5620e86b195..caae6e880e5ed3edb88072336cedd1260bbd7176 100644 (file)
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.228 2004/01/22 02:23:21 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.229 2004/03/02 18:56:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -659,10 +659,10 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
        /*
         * Initialize the junk filter if needed.  SELECT and INSERT queries
         * need a filter if there are any junk attrs in the tlist.      INSERT and
-        * SELECT INTO also need a filter if the top plan node is a scan node
-        * that's not doing projection (else we'll be scribbling on the scan
-        * tuple!)      UPDATE and DELETE always need a filter, since there's
-        * always a junk 'ctid' attribute present --- no need to look first.
+        * SELECT INTO also need a filter if the plan may return raw disk tuples
+        * (else heap_insert will be scribbling on the source relation!).
+        * UPDATE and DELETE always need a filter, since there's always a junk
+        * 'ctid' attribute present --- no need to look first.
         */
        {
                bool            junk_filter_needed = false;
@@ -683,18 +683,9 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
                                        }
                                }
                                if (!junk_filter_needed &&
-                                       (operation == CMD_INSERT || do_select_into))
-                               {
-                                       if (IsA(planstate, SeqScanState) ||
-                                               IsA(planstate, IndexScanState) ||
-                                               IsA(planstate, TidScanState) ||
-                                               IsA(planstate, SubqueryScanState) ||
-                                               IsA(planstate, FunctionScanState))
-                                       {
-                                               if (planstate->ps_ProjInfo == NULL)
-                                                       junk_filter_needed = true;
-                                       }
-                               }
+                                       (operation == CMD_INSERT || do_select_into) &&
+                                       ExecMayReturnRawTuples(planstate))
+                                       junk_filter_needed = true;
                                break;
                        case CMD_UPDATE:
                        case CMD_DELETE:
index 39e07da8afb56cd716387e29a95ad80144de47e9..cc2e49efafc2653216d25102d408a64a0478e6a1 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.106 2004/01/22 02:23:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.107 2004/03/02 18:56:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@ extern void ExecMarkPos(PlanState *node);
 extern void ExecRestrPos(PlanState *node);
 extern bool ExecSupportsMarkRestore(NodeTag plantype);
 extern bool ExecSupportsBackwardScan(Plan *node);
+extern bool ExecMayReturnRawTuples(PlanState *node);
 
 /*
  * prototypes from functions in execGrouping.c