Re: Bug #866: Cursor scrolling broken in 7.3.1 (works in 7.2.1) - Mailing list pgsql-bugs
From | Tom Lane |
---|---|
Subject | Re: Bug #866: Cursor scrolling broken in 7.3.1 (works in 7.2.1) |
Date | |
Msg-id | 11917.1042055050@sss.pgh.pa.us Whole thread Raw |
In response to | Bug #866: Cursor scrolling broken in 7.3.1 (works in 7.2.1) (pgsql-bugs@postgresql.org) |
List | pgsql-bugs |
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;
pgsql-bugs by date: