If you need it right away, here is the patch for the unique-index
problem.  This will be in 7.3.2.

                        regards, tom lane


*** src/backend/access/index/genam.c.orig       Wed Sep  4 17:30:07 2002
--- src/backend/access/index/genam.c    Wed Jan  8 14:25:44 2003
***************
*** 107,112 ****
--- 107,115 ----
        /* mark cached function lookup data invalid; it will be set later */
        scan->fn_getnext.fn_oid = InvalidOid;
  
+       scan->unique_tuple_pos = 0;
+       scan->unique_tuple_mark = 0;
+ 
        pgstat_initstats(&scan->xs_pgstat_info, indexRelation);
  
        /*
*** src/backend/access/index/indexam.c.orig     Wed Sep  4 17:30:08 2002
--- src/backend/access/index/indexam.c  Wed Jan  8 14:34:21 2003
***************
*** 308,313 ****
--- 308,315 ----
        scan->kill_prior_tuple = false;         /* for safety */
        scan->keys_are_unique = false;          /* may be set by amrescan */
        scan->got_tuple = false;
+       scan->unique_tuple_pos = 0;
+       scan->unique_tuple_mark = 0;
  
        OidFunctionCall2(procedure,
                                         PointerGetDatum(scan),
***************
*** 360,365 ****
--- 362,369 ----
        SCAN_CHECKS;
        GET_SCAN_PROCEDURE(markpos, ammarkpos);
  
+       scan->unique_tuple_mark = scan->unique_tuple_pos;
+ 
        OidFunctionCall1(procedure, PointerGetDatum(scan));
  }
  
***************
*** 376,382 ****
        GET_SCAN_PROCEDURE(restrpos, amrestrpos);
  
        scan->kill_prior_tuple = false;         /* for safety */
!       scan->got_tuple = false;
  
        OidFunctionCall1(procedure, PointerGetDatum(scan));
  }
--- 380,392 ----
        GET_SCAN_PROCEDURE(restrpos, amrestrpos);
  
        scan->kill_prior_tuple = false;         /* for safety */
! 
!       /*
!        * We do not reset got_tuple; so if the scan is actually being
!        * short-circuited by index_getnext, the effective position restoration
!        * is done by restoring unique_tuple_pos.
!        */
!       scan->unique_tuple_pos = scan->unique_tuple_mark;
  
        OidFunctionCall1(procedure, PointerGetDatum(scan));
  }
***************
*** 398,403 ****
--- 408,439 ----
  
        SCAN_CHECKS;
  
+       /*
+        * Can skip entering the index AM if we already got a tuple and it
+        * must be unique.  Instead, we need a "short circuit" path that
+        * just keeps track of logical scan position (before/on/after tuple).
+        *
+        * Note that we hold the pin on the single tuple's buffer throughout
+        * the scan once we are in this state.
+        */
+       if (scan->keys_are_unique && scan->got_tuple)
+       {
+               if (ScanDirectionIsForward(direction))
+               {
+                       if (scan->unique_tuple_pos <= 0)
+                               scan->unique_tuple_pos++;
+               }
+               else if (ScanDirectionIsBackward(direction))
+               {
+                       if (scan->unique_tuple_pos >= 0)
+                               scan->unique_tuple_pos--;
+               }
+               if (scan->unique_tuple_pos == 0)
+                       return heapTuple;
+               else
+                       return NULL;
+       }
+ 
        /* Release any previously held pin */
        if (BufferIsValid(scan->xs_cbuf))
        {
***************
*** 408,420 ****
        /* just make sure this is false... */
        scan->kill_prior_tuple = false;
  
-       /*
-        * Can skip entering the index AM if we already got a tuple and it
-        * must be unique.
-        */
-       if (scan->keys_are_unique && scan->got_tuple)
-               return NULL;
- 
        for (;;)
        {
                bool            found;
--- 444,449 ----
***************
*** 474,479 ****
--- 503,514 ----
  
        /* Success exit */
        scan->got_tuple = true;
+ 
+       /*
+        * If we just fetched a known-unique tuple, then subsequent calls will
+        * go through the short-circuit code above.  unique_tuple_pos has been
+        * initialized to 0, which is the correct state ("on row").
+        */
  
        pgstat_count_index_getnext(&scan->xs_pgstat_info);
  
*** src/include/access/relscan.h.orig   Wed Sep  4 17:31:07 2002
--- src/include/access/relscan.h        Wed Jan  8 14:11:13 2003
***************
*** 70,75 ****
--- 70,84 ----
  
        FmgrInfo        fn_getnext;             /* cached lookup info for AM's getnext 
fn */
  
+       /*
+        * If keys_are_unique and got_tuple are both true, we stop calling the
+        * index AM; it is then necessary for index_getnext to keep track of
+        * the logical scan position for itself.  It does that using
+        * unique_tuple_pos: -1 = before row, 0 = on row, +1 = after row.
+        */
+       int                     unique_tuple_pos; /* logical position */
+       int                     unique_tuple_mark; /* logical marked position */
+ 
        PgStat_Info xs_pgstat_info; /* statistics collector hook */
  } IndexScanDescData;
  

---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to [EMAIL PROTECTED] so that your
message can get through to the mailing list cleanly

Reply via email to