88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.58 2005/05/17 03:34:18 neilc Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.59 2005/06/27 12:45:22 teodor Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
2424static void gistregscan (IndexScanDesc scan );
2525static void gistdropscan (IndexScanDesc scan );
2626static void gistadjone (IndexScanDesc scan , int op , BlockNumber blkno ,
27- OffsetNumber offnum );
28- static void adjuststack (GISTSTACK * stk , BlockNumber blkno );
29- static void adjustiptr (IndexScanDesc scan , ItemPointer iptr ,
30- int op , BlockNumber blkno , OffsetNumber offnum );
31- static void gistfreestack (GISTSTACK * s );
27+ OffsetNumber offnum , XLogRecPtr newlsn , XLogRecPtr oldlsn );
28+ static void adjustiptr (IndexScanDesc scan , ItemPointer iptr , GISTSearchStack * stk ,
29+ int op , BlockNumber blkno , OffsetNumber offnum , XLogRecPtr newlsn , XLogRecPtr oldlsn );
30+ static void gistfreestack (GISTSearchStack * s );
3231
3332/*
3433 * Whenever we start a GiST scan in a backend, we register it in
@@ -139,7 +138,7 @@ gistmarkpos(PG_FUNCTION_ARGS)
139138{
140139 IndexScanDesc scan = (IndexScanDesc ) PG_GETARG_POINTER (0 );
141140 GISTScanOpaque so ;
142- GISTSTACK * o ,
141+ GISTSearchStack * o ,
143142 * n ,
144143 * tmp ;
145144
@@ -156,12 +155,13 @@ gistmarkpos(PG_FUNCTION_ARGS)
156155 /* copy the parent stack from the current item data */
157156 while (n != NULL )
158157 {
159- tmp = (GISTSTACK * ) palloc (sizeof (GISTSTACK ));
160- tmp -> offset = n -> offset ;
158+ tmp = (GISTSearchStack * ) palloc (sizeof (GISTSearchStack ));
159+ tmp -> lsn = n -> lsn ;
160+ tmp -> parentlsn = n -> parentlsn ;
161161 tmp -> block = n -> block ;
162- tmp -> parent = o ;
162+ tmp -> next = o ;
163163 o = tmp ;
164- n = n -> parent ;
164+ n = n -> next ;
165165 }
166166
167167 gistfreestack (so -> markstk );
@@ -187,7 +187,7 @@ gistrestrpos(PG_FUNCTION_ARGS)
187187{
188188 IndexScanDesc scan = (IndexScanDesc ) PG_GETARG_POINTER (0 );
189189 GISTScanOpaque so ;
190- GISTSTACK * o ,
190+ GISTSearchStack * o ,
191191 * n ,
192192 * tmp ;
193193
@@ -204,12 +204,13 @@ gistrestrpos(PG_FUNCTION_ARGS)
204204 /* copy the parent stack from the current item data */
205205 while (n != NULL )
206206 {
207- tmp = (GISTSTACK * ) palloc (sizeof (GISTSTACK ));
208- tmp -> offset = n -> offset ;
207+ tmp = (GISTSearchStack * ) palloc (sizeof (GISTSearchStack ));
208+ tmp -> lsn = n -> lsn ;
209+ tmp -> parentlsn = n -> parentlsn ;
209210 tmp -> block = n -> block ;
210- tmp -> parent = o ;
211+ tmp -> next = o ;
211212 o = tmp ;
212- n = n -> parent ;
213+ n = n -> next ;
213214 }
214215
215216 gistfreestack (so -> stack );
@@ -253,6 +254,7 @@ gistendscan(PG_FUNCTION_ARGS)
253254 pfree (scan -> opaque );
254255 }
255256
257+
256258 gistdropscan (scan );
257259
258260 PG_RETURN_VOID ();
@@ -331,16 +333,19 @@ ReleaseResources_gist(void)
331333}
332334
333335void
334- gistadjscans (Relation rel , int op , BlockNumber blkno , OffsetNumber offnum )
336+ gistadjscans (Relation rel , int op , BlockNumber blkno , OffsetNumber offnum , XLogRecPtr newlsn , XLogRecPtr oldlsn )
335337{
336338 GISTScanList l ;
337339 Oid relid ;
338340
341+ if ( XLogRecPtrIsInvalid (newlsn ) || XLogRecPtrIsInvalid (oldlsn ) )
342+ return ;
343+
339344 relid = RelationGetRelid (rel );
340345 for (l = GISTScans ; l != NULL ; l = l -> gsl_next )
341346 {
342347 if (l -> gsl_scan -> indexRelation -> rd_id == relid )
343- gistadjone (l -> gsl_scan , op , blkno , offnum );
348+ gistadjone (l -> gsl_scan , op , blkno , offnum , newlsn , oldlsn );
344349 }
345350}
346351
@@ -358,20 +363,12 @@ static void
358363gistadjone (IndexScanDesc scan ,
359364 int op ,
360365 BlockNumber blkno ,
361- OffsetNumber offnum )
366+ OffsetNumber offnum , XLogRecPtr newlsn , XLogRecPtr oldlsn )
362367{
363- GISTScanOpaque so ;
364-
365- adjustiptr (scan , & (scan -> currentItemData ), op , blkno , offnum );
366- adjustiptr (scan , & (scan -> currentMarkData ), op , blkno , offnum );
367-
368- so = (GISTScanOpaque ) scan -> opaque ;
368+ GISTScanOpaque so = (GISTScanOpaque ) scan -> opaque ;
369369
370- if (op == GISTOP_SPLIT )
371- {
372- adjuststack (so -> stack , blkno );
373- adjuststack (so -> markstk , blkno );
374- }
370+ adjustiptr (scan , & (scan -> currentItemData ), so -> stack , op , blkno , offnum , newlsn , oldlsn );
371+ adjustiptr (scan , & (scan -> currentMarkData ), so -> markstk , op , blkno , offnum , newlsn , oldlsn );
375372}
376373
377374/*
@@ -383,10 +380,10 @@ gistadjone(IndexScanDesc scan,
383380 */
384381static void
385382adjustiptr (IndexScanDesc scan ,
386- ItemPointer iptr ,
383+ ItemPointer iptr , GISTSearchStack * stk ,
387384 int op ,
388385 BlockNumber blkno ,
389- OffsetNumber offnum )
386+ OffsetNumber offnum , XLogRecPtr newlsn , XLogRecPtr oldlsn )
390387{
391388 OffsetNumber curoff ;
392389 GISTScanOpaque so ;
@@ -402,7 +399,7 @@ adjustiptr(IndexScanDesc scan,
402399 {
403400 case GISTOP_DEL :
404401 /* back up one if we need to */
405- if (curoff >= offnum )
402+ if (curoff >= offnum && XLByteEQ ( stk -> lsn , oldlsn ) ) /* the same vesrion of page */
406403 {
407404 if (curoff > FirstOffsetNumber )
408405 {
@@ -421,56 +418,22 @@ adjustiptr(IndexScanDesc scan,
421418 else
422419 so -> flags |= GS_MRKBEFORE ;
423420 }
421+ stk -> lsn = newlsn ;
424422 }
425423 break ;
426-
427- case GISTOP_SPLIT :
428- /* back to start of page on split */
429- ItemPointerSet (iptr , blkno , FirstOffsetNumber );
430- if (iptr == & (scan -> currentItemData ))
431- so -> flags &= ~GS_CURBEFORE ;
432- else
433- so -> flags &= ~GS_MRKBEFORE ;
434- break ;
435-
436424 default :
437425 elog (ERROR , "Bad operation in GiST scan adjust: %d" , op );
438426 }
439427 }
440428 }
441429}
442430
443- /*
444- * adjuststack() -- adjust the supplied stack for a split on a page in
445- * the index we're scanning.
446- *
447- * If a page on our parent stack has split, we need to back up to the
448- * beginning of the page and rescan it. The reason for this is that
449- * the split algorithm for GiSTs doesn't order tuples in any useful
450- * way on a single page. This means on that a split, we may wind up
451- * looking at some heap tuples more than once. This is handled in the
452- * access method update code for heaps; if we've modified the tuple we
453- * are looking at already in this transaction, we ignore the update
454- * request.
455- */
456- static void
457- adjuststack (GISTSTACK * stk , BlockNumber blkno )
458- {
459- while (stk != NULL )
460- {
461- if (stk -> block == blkno )
462- stk -> offset = FirstOffsetNumber ;
463-
464- stk = stk -> parent ;
465- }
466- }
467-
468431static void
469- gistfreestack (GISTSTACK * s )
432+ gistfreestack (GISTSearchStack * s )
470433{
471434 while (s != NULL )
472435 {
473- GISTSTACK * p = s -> parent ;
436+ GISTSearchStack * p = s -> next ;
474437 pfree (s );
475438 s = p ;
476439 }
0 commit comments