Do not allow Unique nodes to be scanned backwards. The code claimed that it
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 5 Aug 2008 21:28:42 +0000 (21:28 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 5 Aug 2008 21:28:42 +0000 (21:28 +0000)
would work, but in fact it didn't return the same rows when moving backwards
as when moving forwards.  This would have no visible effect in a DISTINCT
query (at least assuming the column datatypes use a strong definition of
equality), but it gave entirely wrong answers for DISTINCT ON queries.

src/backend/executor/execAmi.c
src/backend/executor/nodeUnique.c

index c7162e8f061a62e48b676214cde1a24eee22aa93..2b40ac19dc53a032631cb134e8f7d729a9361bab 100644 (file)
@@ -413,9 +413,6 @@ ExecSupportsBackwardScan(Plan *node)
                case T_Sort:
                        return true;
 
-               case T_Unique:
-                       return ExecSupportsBackwardScan(outerPlan(node));
-
                case T_Limit:
                        return ExecSupportsBackwardScan(outerPlan(node));
 
index 5e7cd933dbd3117ce935ac2c758b30e5d6cf71cc..f8809c26fbc45cca76f4c55e50019ef05656f0a7 100644 (file)
@@ -15,7 +15,7 @@
 /*
  * INTERFACE ROUTINES
  *             ExecUnique              - generate a unique'd temporary relation
- *             ExecInitUnique  - initialize node and subnodes..
+ *             ExecInitUnique  - initialize node and subnodes
  *             ExecEndUnique   - shutdown node and subnodes
  *
  * NOTES
@@ -32,9 +32,6 @@
 
 /* ----------------------------------------------------------------
  *             ExecUnique
- *
- *             This is a very simple node which filters out duplicate
- *             tuples from a stream of sorted tuples from a subplan.
  * ----------------------------------------------------------------
  */
 TupleTableSlot *                               /* return: a tuple or NULL */
@@ -54,11 +51,7 @@ ExecUnique(UniqueState *node)
        /*
         * now loop, returning only non-duplicate tuples. We assume that the
         * tuples arrive in sorted order so we can detect duplicates easily.
-        *
-        * We return the first tuple from each group of duplicates (or the last
-        * tuple of each group, when moving backwards).  At either end of the
-        * subplan, clear the result slot so that we correctly return the
-        * first/last tuple when reversing direction.
+        * The first tuple of each group is returned.
         */
        for (;;)
        {
@@ -68,13 +61,13 @@ ExecUnique(UniqueState *node)
                slot = ExecProcNode(outerPlan);
                if (TupIsNull(slot))
                {
-                       /* end of subplan; reset in case we change direction */
+                       /* end of subplan, so we're done */
                        ExecClearTuple(resultTupleSlot);
                        return NULL;
                }
 
                /*
-                * Always return the first/last tuple from the subplan.
+                * Always return the first tuple from the subplan.
                 */
                if (TupIsNull(resultTupleSlot))
                        break;
@@ -113,7 +106,7 @@ ExecInitUnique(Unique *node, EState *estate, int eflags)
        UniqueState *uniquestate;
 
        /* check for unsupported flags */
-       Assert(!(eflags & EXEC_FLAG_MARK));
+       Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
 
        /*
         * create state structure