]> granicus.if.org Git - postgresql/blob - src/backend/access/gist/gistscan.c
106714511a815e072e43047039802558eb44b3a9
[postgresql] / src / backend / access / gist / gistscan.c
1 /*-------------------------------------------------------------------------
2  *
3  * gistscan.c
4  *        routines to manage scans on GiST index relations
5  *
6  *
7  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * IDENTIFICATION
11  *        src/backend/access/gist/gistscan.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/genam.h"
18 #include "access/gist_private.h"
19 #include "access/gistscan.h"
20 #include "access/relscan.h"
21 #include "storage/bufmgr.h"
22 #include "utils/memutils.h"
23
24 static void gistfreestack(GISTSearchStack *s);
25
26 Datum
27 gistbeginscan(PG_FUNCTION_ARGS)
28 {
29         Relation        r = (Relation) PG_GETARG_POINTER(0);
30         int                     nkeys = PG_GETARG_INT32(1);
31         int                     norderbys = PG_GETARG_INT32(2);
32         IndexScanDesc scan;
33         GISTScanOpaque so;
34
35         /* no order by operators allowed */
36         Assert(norderbys == 0);
37
38         scan = RelationGetIndexScan(r, nkeys, norderbys);
39
40         /* initialize opaque data */
41         so = (GISTScanOpaque) palloc(sizeof(GISTScanOpaqueData));
42         so->stack = NULL;
43         so->tempCxt = createTempGistContext();
44         so->curbuf = InvalidBuffer;
45         so->giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE));
46         initGISTstate(so->giststate, scan->indexRelation);
47
48         scan->opaque = so;
49
50         PG_RETURN_POINTER(scan);
51 }
52
53 Datum
54 gistrescan(PG_FUNCTION_ARGS)
55 {
56         IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
57         ScanKey         key = (ScanKey) PG_GETARG_POINTER(1);
58         /* remaining arguments are ignored */
59         GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
60         int                     i;
61
62         /* rescan an existing indexscan --- reset state */
63         gistfreestack(so->stack);
64         so->stack = NULL;
65         /* drop pins on buffers -- no locks held */
66         if (BufferIsValid(so->curbuf))
67         {
68                 ReleaseBuffer(so->curbuf);
69                 so->curbuf = InvalidBuffer;
70         }
71
72         /*
73          * Clear all the pointers.
74          */
75         ItemPointerSetInvalid(&so->curpos);
76         so->nPageData = so->curPageData = 0;
77
78         so->qual_ok = true;
79
80         /* Update scan key, if a new one is given */
81         if (key && scan->numberOfKeys > 0)
82         {
83                 memmove(scan->keyData, key,
84                                 scan->numberOfKeys * sizeof(ScanKeyData));
85
86                 /*
87                  * Modify the scan key so that all the Consistent method is called for
88                  * all comparisons. The original operator is passed to the Consistent
89                  * function in the form of its strategy number, which is available
90                  * from the sk_strategy field, and its subtype from the sk_subtype
91                  * field.
92                  *
93                  * Next, if any of keys is a NULL and that key is not marked with
94                  * SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie, we
95                  * assume all indexable operators are strict).
96                  */
97                 for (i = 0; i < scan->numberOfKeys; i++)
98                 {
99                         ScanKey         skey = &(scan->keyData[i]);
100
101                         skey->sk_func = so->giststate->consistentFn[skey->sk_attno - 1];
102
103                         if (skey->sk_flags & SK_ISNULL)
104                         {
105                                 if (!(skey->sk_flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL)))
106                                         so->qual_ok = false;
107                         }
108                 }
109         }
110
111         PG_RETURN_VOID();
112 }
113
114 Datum
115 gistmarkpos(PG_FUNCTION_ARGS)
116 {
117         elog(ERROR, "GiST does not support mark/restore");
118         PG_RETURN_VOID();
119 }
120
121 Datum
122 gistrestrpos(PG_FUNCTION_ARGS)
123 {
124         elog(ERROR, "GiST does not support mark/restore");
125         PG_RETURN_VOID();
126 }
127
128 Datum
129 gistendscan(PG_FUNCTION_ARGS)
130 {
131         IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
132         GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
133
134         gistfreestack(so->stack);
135         if (so->giststate != NULL)
136                 freeGISTstate(so->giststate);
137         /* drop pins on buffers -- we aren't holding any locks */
138         if (BufferIsValid(so->curbuf))
139                 ReleaseBuffer(so->curbuf);
140         MemoryContextDelete(so->tempCxt);
141         pfree(so);
142
143         PG_RETURN_VOID();
144 }
145
146 static void
147 gistfreestack(GISTSearchStack *s)
148 {
149         while (s != NULL)
150         {
151                 GISTSearchStack *p = s->next;
152
153                 pfree(s);
154                 s = p;
155         }
156 }