1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-05 09:19:17 +03:00

Do not allow Unique nodes to be scanned backwards. The code claimed that it

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.
This commit is contained in:
Tom Lane 2008-08-05 21:28:42 +00:00
parent a1b631b353
commit aab9979c5c
2 changed files with 7 additions and 17 deletions

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.89.2.2 2008/07/10 01:17:44 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.89.2.3 2008/08/05 21:28:42 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -413,9 +413,6 @@ ExecSupportsBackwardScan(Plan *node)
case T_Sort: case T_Sort:
return true; return true;
case T_Unique:
return ExecSupportsBackwardScan(outerPlan(node));
case T_Limit: case T_Limit:
return ExecSupportsBackwardScan(outerPlan(node)); return ExecSupportsBackwardScan(outerPlan(node));

View File

@ -8,14 +8,14 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeUnique.c,v 1.53 2006/07/14 14:52:19 momjian Exp $ * $PostgreSQL: pgsql/src/backend/executor/nodeUnique.c,v 1.53.2.1 2008/08/05 21:28:42 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
/* /*
* INTERFACE ROUTINES * INTERFACE ROUTINES
* ExecUnique - generate a unique'd temporary relation * ExecUnique - generate a unique'd temporary relation
* ExecInitUnique - initialize node and subnodes.. * ExecInitUnique - initialize node and subnodes
* ExecEndUnique - shutdown node and subnodes * ExecEndUnique - shutdown node and subnodes
* *
* NOTES * NOTES
@ -32,9 +32,6 @@
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecUnique * 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 */ TupleTableSlot * /* return: a tuple or NULL */
@ -54,11 +51,7 @@ ExecUnique(UniqueState *node)
/* /*
* now loop, returning only non-duplicate tuples. We assume that the * now loop, returning only non-duplicate tuples. We assume that the
* tuples arrive in sorted order so we can detect duplicates easily. * tuples arrive in sorted order so we can detect duplicates easily.
* * The first tuple of each group is returned.
* 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.
*/ */
for (;;) for (;;)
{ {
@ -68,13 +61,13 @@ ExecUnique(UniqueState *node)
slot = ExecProcNode(outerPlan); slot = ExecProcNode(outerPlan);
if (TupIsNull(slot)) if (TupIsNull(slot))
{ {
/* end of subplan; reset in case we change direction */ /* end of subplan, so we're done */
ExecClearTuple(resultTupleSlot); ExecClearTuple(resultTupleSlot);
return NULL; return NULL;
} }
/* /*
* Always return the first/last tuple from the subplan. * Always return the first tuple from the subplan.
*/ */
if (TupIsNull(resultTupleSlot)) if (TupIsNull(resultTupleSlot))
break; break;
@ -113,7 +106,7 @@ ExecInitUnique(Unique *node, EState *estate, int eflags)
UniqueState *uniquestate; UniqueState *uniquestate;
/* check for unsupported flags */ /* check for unsupported flags */
Assert(!(eflags & EXEC_FLAG_MARK)); Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
/* /*
* create state structure * create state structure