From 0489783011ee277476bd9076767b39f08c0e0cd1 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 23 Mar 2003 23:01:03 +0000 Subject: [PATCH] Adjust amrescan code so that it's allowed to call index_rescan with a NULL key pointer, indicating that the existing scan key should be reused. This behavior isn't used yet but will be needed for my planned fix to the keys_are_unique code. --- src/backend/access/gist/gistscan.c | 54 +++++++++++++----------------- src/backend/access/hash/hash.c | 10 +++--- src/backend/access/index/indexam.c | 10 ++++-- src/backend/access/nbtree/nbtree.c | 7 ++-- src/backend/access/rtree/rtscan.c | 54 ++++++++++++++---------------- 5 files changed, 63 insertions(+), 72 deletions(-) diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c index 9c1c92a880..8a23b9b115 100644 --- a/src/backend/access/gist/gistscan.c +++ b/src/backend/access/gist/gistscan.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.43 2002/06/20 20:29:24 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.44 2003/03/23 23:01:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -78,28 +78,14 @@ gistrescan(PG_FUNCTION_ARGS) ItemPointerSetInvalid(&s->currentItemData); ItemPointerSetInvalid(&s->currentMarkData); - if (s->numberOfKeys > 0) - { - memmove(s->keyData, - key, - s->numberOfKeys * sizeof(ScanKeyData)); - } - p = (GISTScanOpaque) s->opaque; if (p != (GISTScanOpaque) NULL) { + /* rescan an existing indexscan --- reset state */ gistfreestack(p->s_stack); gistfreestack(p->s_markstk); p->s_stack = p->s_markstk = (GISTSTACK *) NULL; p->s_flags = 0x0; - for (i = 0; i < s->numberOfKeys; i++) - { - s->keyData[i].sk_procedure - = RelationGetGISTStrategy(s->indexRelation, - s->keyData[i].sk_attno, - s->keyData[i].sk_procedure); - s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1]; - } } else { @@ -110,22 +96,28 @@ gistrescan(PG_FUNCTION_ARGS) s->opaque = p; p->giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE)); initGISTstate(p->giststate, s->indexRelation); - if (s->numberOfKeys > 0) + } - /* - * * Play games here with the scan key to use the Consistent * - * function for all comparisons: * 1) the sk_procedure field - * will now be used to hold the * strategy number * 2) the - * sk_func field will point to the Consistent function - */ - for (i = 0; i < s->numberOfKeys; i++) - { - s->keyData[i].sk_procedure = - RelationGetGISTStrategy(s->indexRelation, - s->keyData[i].sk_attno, - s->keyData[i].sk_procedure); - s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1]; - } + /* Update scan key, if a new one is given */ + if (key && s->numberOfKeys > 0) + { + memmove(s->keyData, + key, + s->numberOfKeys * sizeof(ScanKeyData)); + /* + * Play games here with the scan key to use the Consistent + * function for all comparisons: 1) the sk_procedure field + * will now be used to hold the strategy number 2) the + * sk_func field will point to the Consistent function + */ + for (i = 0; i < s->numberOfKeys; i++) + { + s->keyData[i].sk_procedure = + RelationGetGISTStrategy(s->indexRelation, + s->keyData[i].sk_attno, + s->keyData[i].sk_procedure); + s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1]; + } } PG_RETURN_VOID(); diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 705041f7d2..f3534d2e17 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.62 2003/02/24 00:57:17 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.63 2003/03/23 23:01:03 tgl Exp $ * * NOTES * This file contains only the public interface routines. @@ -302,10 +302,8 @@ hashrescan(PG_FUNCTION_ARGS) { IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); ScanKey scankey = (ScanKey) PG_GETARG_POINTER(1); + HashScanOpaque so = (HashScanOpaque) scan->opaque; ItemPointer iptr; - HashScanOpaque so; - - so = (HashScanOpaque) scan->opaque; /* we hold a read lock on the current page in the scan */ if (ItemPointerIsValid(iptr = &(scan->currentItemData))) @@ -321,8 +319,8 @@ hashrescan(PG_FUNCTION_ARGS) ItemPointerSetInvalid(iptr); } - /* reset the scan key */ - if (scan->numberOfKeys > 0) + /* Update scan key, if a new one is given */ + if (scankey && scan->numberOfKeys > 0) { memmove(scan->keyData, scankey, diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index d045bafc1c..2f0c6aac52 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.64 2003/02/22 00:45:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.65 2003/03/23 23:01:03 tgl Exp $ * * INTERFACE ROUTINES * index_open - open an index relation by relation OID @@ -294,8 +294,12 @@ index_beginscan(Relation heapRelation, * index_rescan - (re)start a scan of an index * * The caller may specify a new set of scankeys (but the number of keys - * cannot change). Note that this is also called when first starting - * an indexscan; see RelationGetIndexScan. + * cannot change). To restart the scan without changing keys, pass NULL + * for the key array. + * + * Note that this is also called when first starting an indexscan; + * see RelationGetIndexScan. Keys *must* be passed in that case, + * unless scan->numberOfKeys is zero. * ---------------- */ void diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index b1722244e6..a35901b47c 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.101 2003/03/04 21:51:20 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.102 2003/03/23 23:01:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -396,6 +396,7 @@ btrescan(PG_FUNCTION_ARGS) so->keyData = (ScanKey) palloc(scan->numberOfKeys * sizeof(ScanKeyData)); else so->keyData = (ScanKey) NULL; + so->numberOfKeys = scan->numberOfKeys; scan->opaque = so; } @@ -420,12 +421,12 @@ btrescan(PG_FUNCTION_ARGS) * Reset the scan keys. Note that keys ordering stuff moved to * _bt_first. - vadim 05/05/97 */ - so->numberOfKeys = scan->numberOfKeys; - if (scan->numberOfKeys > 0) + if (scankey && scan->numberOfKeys > 0) { memmove(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); + so->numberOfKeys = scan->numberOfKeys; memmove(so->keyData, scankey, so->numberOfKeys * sizeof(ScanKeyData)); diff --git a/src/backend/access/rtree/rtscan.c b/src/backend/access/rtree/rtscan.c index 52aedeae2b..a0b9883cfe 100644 --- a/src/backend/access/rtree/rtscan.c +++ b/src/backend/access/rtree/rtscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.42 2002/06/20 20:29:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.43 2003/03/23 23:01:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -80,22 +80,14 @@ rtrescan(PG_FUNCTION_ARGS) ItemPointerSetInvalid(&s->currentItemData); ItemPointerSetInvalid(&s->currentMarkData); - if (s->numberOfKeys > 0) - { - memmove(s->keyData, - key, - s->numberOfKeys * sizeof(ScanKeyData)); - } - p = (RTreeScanOpaque) s->opaque; if (p != (RTreeScanOpaque) NULL) { + /* rescan an existing indexscan --- reset state */ freestack(p->s_stack); freestack(p->s_markstk); p->s_stack = p->s_markstk = (RTSTACK *) NULL; p->s_flags = 0x0; - for (i = 0; i < s->numberOfKeys; i++) - p->s_internalKey[i].sk_argument = s->keyData[i].sk_argument; } else { @@ -106,28 +98,32 @@ rtrescan(PG_FUNCTION_ARGS) p->s_flags = 0x0; s->opaque = p; if (s->numberOfKeys > 0) - { p->s_internalKey = (ScanKey) palloc(sizeof(ScanKeyData) * s->numberOfKeys); + } - /* - * Scans on internal pages use different operators than they - * do on leaf pages. For example, if the user wants all boxes - * that exactly match (x1,y1,x2,y2), then on internal pages we - * need to find all boxes that contain (x1,y1,x2,y2). - */ + /* Update scan key, if a new one is given */ + if (key && s->numberOfKeys > 0) + { + memmove(s->keyData, + key, + s->numberOfKeys * sizeof(ScanKeyData)); - for (i = 0; i < s->numberOfKeys; i++) - { - p->s_internalKey[i].sk_argument = s->keyData[i].sk_argument; - internal_proc = RTMapOperator(s->indexRelation, - s->keyData[i].sk_attno, - s->keyData[i].sk_procedure); - ScanKeyEntryInitialize(&(p->s_internalKey[i]), - s->keyData[i].sk_flags, - s->keyData[i].sk_attno, - internal_proc, - s->keyData[i].sk_argument); - } + /* + * Scans on internal pages use different operators than they + * do on leaf pages. For example, if the user wants all boxes + * that exactly match (x1,y1,x2,y2), then on internal pages we + * need to find all boxes that contain (x1,y1,x2,y2). + */ + for (i = 0; i < s->numberOfKeys; i++) + { + internal_proc = RTMapOperator(s->indexRelation, + s->keyData[i].sk_attno, + s->keyData[i].sk_procedure); + ScanKeyEntryInitialize(&(p->s_internalKey[i]), + s->keyData[i].sk_flags, + s->keyData[i].sk_attno, + internal_proc, + s->keyData[i].sk_argument); } }