~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/access/index/genam.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * genam.c
 
4
 *        general index access method routines
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.44 2004-12-31 21:59:19 pgsql Exp $
 
12
 *
 
13
 * NOTES
 
14
 *        many of the old access method routines have been turned into
 
15
 *        macros and moved to genam.h -cim 4/30/91
 
16
 *
 
17
 *-------------------------------------------------------------------------
 
18
 */
 
19
 
 
20
#include "postgres.h"
 
21
 
 
22
#include "access/genam.h"
 
23
#include "access/heapam.h"
 
24
#include "miscadmin.h"
 
25
#include "pgstat.h"
 
26
 
 
27
 
 
28
/* ----------------------------------------------------------------
 
29
 *              general access method routines
 
30
 *
 
31
 *              All indexed access methods use an identical scan structure.
 
32
 *              We don't know how the various AMs do locking, however, so we don't
 
33
 *              do anything about that here.
 
34
 *
 
35
 *              The intent is that an AM implementor will define a beginscan routine
 
36
 *              that calls RelationGetIndexScan, to fill in the scan, and then does
 
37
 *              whatever kind of locking he wants.
 
38
 *
 
39
 *              At the end of a scan, the AM's endscan routine undoes the locking,
 
40
 *              but does *not* call IndexScanEnd --- the higher-level index_endscan
 
41
 *              routine does that.      (We can't do it in the AM because index_endscan
 
42
 *              still needs to touch the IndexScanDesc after calling the AM.)
 
43
 *
 
44
 *              Because of this, the AM does not have a choice whether to call
 
45
 *              RelationGetIndexScan or not; its beginscan routine must return an
 
46
 *              object made by RelationGetIndexScan.  This is kinda ugly but not
 
47
 *              worth cleaning up now.
 
48
 * ----------------------------------------------------------------
 
49
 */
 
50
 
 
51
/* ----------------
 
52
 *      RelationGetIndexScan -- Create and fill an IndexScanDesc.
 
53
 *
 
54
 *              This routine creates an index scan structure and sets its contents
 
55
 *              up correctly. This routine calls AMrescan to set up the scan with
 
56
 *              the passed key.
 
57
 *
 
58
 *              Parameters:
 
59
 *                              indexRelation -- index relation for scan.
 
60
 *                              nkeys -- count of scan keys.
 
61
 *                              key -- array of scan keys to restrict the index scan.
 
62
 *
 
63
 *              Returns:
 
64
 *                              An initialized IndexScanDesc.
 
65
 * ----------------
 
66
 */
 
67
IndexScanDesc
 
68
RelationGetIndexScan(Relation indexRelation,
 
69
                                         int nkeys, ScanKey key)
 
70
{
 
71
        IndexScanDesc scan;
 
72
 
 
73
        scan = (IndexScanDesc) palloc(sizeof(IndexScanDescData));
 
74
 
 
75
        scan->heapRelation = NULL;      /* may be set later */
 
76
        scan->indexRelation = indexRelation;
 
77
        scan->xs_snapshot = SnapshotNow;        /* may be set later */
 
78
        scan->numberOfKeys = nkeys;
 
79
 
 
80
        /*
 
81
         * We allocate the key space here, but the AM is responsible for
 
82
         * actually filling it from the passed key array.
 
83
         */
 
84
        if (nkeys > 0)
 
85
                scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
 
86
        else
 
87
                scan->keyData = NULL;
 
88
 
 
89
        scan->kill_prior_tuple = false;
 
90
        scan->ignore_killed_tuples = true;      /* default setting */
 
91
        scan->keys_are_unique = false;          /* may be set by index AM */
 
92
        scan->got_tuple = false;
 
93
 
 
94
        scan->opaque = NULL;
 
95
 
 
96
        ItemPointerSetInvalid(&scan->currentItemData);
 
97
        ItemPointerSetInvalid(&scan->currentMarkData);
 
98
 
 
99
        ItemPointerSetInvalid(&scan->xs_ctup.t_self);
 
100
        scan->xs_ctup.t_datamcxt = NULL;
 
101
        scan->xs_ctup.t_data = NULL;
 
102
        scan->xs_cbuf = InvalidBuffer;
 
103
 
 
104
        /* mark cached function lookup data invalid; it will be set later */
 
105
        scan->fn_getnext.fn_oid = InvalidOid;
 
106
 
 
107
        scan->unique_tuple_pos = 0;
 
108
        scan->unique_tuple_mark = 0;
 
109
 
 
110
        pgstat_initstats(&scan->xs_pgstat_info, indexRelation);
 
111
 
 
112
        /*
 
113
         * Let the AM fill in the key and any opaque data it wants.
 
114
         */
 
115
        index_rescan(scan, key);
 
116
 
 
117
        return scan;
 
118
}
 
119
 
 
120
/* ----------------
 
121
 *      IndexScanEnd -- End an index scan.
 
122
 *
 
123
 *              This routine just releases the storage acquired by
 
124
 *              RelationGetIndexScan().  Any AM-level resources are
 
125
 *              assumed to already have been released by the AM's
 
126
 *              endscan routine.
 
127
 *
 
128
 *      Returns:
 
129
 *              None.
 
130
 * ----------------
 
131
 */
 
132
void
 
133
IndexScanEnd(IndexScanDesc scan)
 
134
{
 
135
        if (scan->keyData != NULL)
 
136
                pfree(scan->keyData);
 
137
 
 
138
        pfree(scan);
 
139
}
 
140
 
 
141
 
 
142
/* ----------------------------------------------------------------
 
143
 *              heap-or-index-scan access to system catalogs
 
144
 *
 
145
 *              These functions support system catalog accesses that normally use
 
146
 *              an index but need to be capable of being switched to heap scans
 
147
 *              if the system indexes are unavailable.
 
148
 *
 
149
 *              The specified scan keys must be compatible with the named index.
 
150
 *              Generally this means that they must constrain either all columns
 
151
 *              of the index, or the first K columns of an N-column index.
 
152
 *
 
153
 *              These routines could work with non-system tables, actually,
 
154
 *              but they're only useful when there is a known index to use with
 
155
 *              the given scan keys; so in practice they're only good for
 
156
 *              predetermined types of scans of system catalogs.
 
157
 * ----------------------------------------------------------------
 
158
 */
 
159
 
 
160
/*
 
161
 * systable_beginscan --- set up for heap-or-index scan
 
162
 *
 
163
 *      rel: catalog to scan, already opened and suitably locked
 
164
 *      indexRelname: name of index to conditionally use
 
165
 *      indexOK: if false, forces a heap scan (see notes below)
 
166
 *      snapshot: time qual to use (usually should be SnapshotNow)
 
167
 *      nkeys, key: scan keys
 
168
 *
 
169
 * The attribute numbers in the scan key should be set for the heap case.
 
170
 * If we choose to index, we reset them to 1..n to reference the index
 
171
 * columns.  Note this means there must be one scankey qualification per
 
172
 * index column!  This is checked by the Asserts in the normal, index-using
 
173
 * case, but won't be checked if the heapscan path is taken.
 
174
 *
 
175
 * The routine checks the normal cases for whether an indexscan is safe,
 
176
 * but caller can make additional checks and pass indexOK=false if needed.
 
177
 * In standard case indexOK can simply be constant TRUE.
 
178
 */
 
179
SysScanDesc
 
180
systable_beginscan(Relation heapRelation,
 
181
                                   const char *indexRelname,
 
182
                                   bool indexOK,
 
183
                                   Snapshot snapshot,
 
184
                                   int nkeys, ScanKey key)
 
185
{
 
186
        SysScanDesc sysscan;
 
187
        Relation        irel;
 
188
 
 
189
        if (indexOK && !IsIgnoringSystemIndexes())
 
190
        {
 
191
                /* We assume it's a system index, so index_openr is OK */
 
192
                irel = index_openr(indexRelname);
 
193
 
 
194
                if (ReindexIsProcessingIndex(RelationGetRelid(irel)))
 
195
                {
 
196
                        /* oops, can't use index that's being rebuilt */
 
197
                        index_close(irel);
 
198
                        irel = NULL;
 
199
                }
 
200
        }
 
201
        else
 
202
                irel = NULL;
 
203
 
 
204
        sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData));
 
205
 
 
206
        sysscan->heap_rel = heapRelation;
 
207
        sysscan->irel = irel;
 
208
 
 
209
        if (irel)
 
210
        {
 
211
                int                     i;
 
212
 
 
213
                /*
 
214
                 * Change attribute numbers to be index column numbers.
 
215
                 *
 
216
                 * This code could be generalized to search for the index key numbers
 
217
                 * to substitute, but for now there's no need.
 
218
                 */
 
219
                for (i = 0; i < nkeys; i++)
 
220
                {
 
221
                        Assert(key[i].sk_attno == irel->rd_index->indkey[i]);
 
222
                        key[i].sk_attno = i + 1;
 
223
                }
 
224
 
 
225
                sysscan->iscan = index_beginscan(heapRelation, irel, snapshot,
 
226
                                                                                 nkeys, key);
 
227
                sysscan->scan = NULL;
 
228
        }
 
229
        else
 
230
        {
 
231
                sysscan->scan = heap_beginscan(heapRelation, snapshot, nkeys, key);
 
232
                sysscan->iscan = NULL;
 
233
        }
 
234
 
 
235
        return sysscan;
 
236
}
 
237
 
 
238
/*
 
239
 * systable_getnext --- get next tuple in a heap-or-index scan
 
240
 *
 
241
 * Returns NULL if no more tuples available.
 
242
 *
 
243
 * Note that returned tuple is a reference to data in a disk buffer;
 
244
 * it must not be modified, and should be presumed inaccessible after
 
245
 * next getnext() or endscan() call.
 
246
 */
 
247
HeapTuple
 
248
systable_getnext(SysScanDesc sysscan)
 
249
{
 
250
        HeapTuple       htup;
 
251
 
 
252
        if (sysscan->irel)
 
253
                htup = index_getnext(sysscan->iscan, ForwardScanDirection);
 
254
        else
 
255
                htup = heap_getnext(sysscan->scan, ForwardScanDirection);
 
256
 
 
257
        return htup;
 
258
}
 
259
 
 
260
/*
 
261
 * systable_endscan --- close scan, release resources
 
262
 *
 
263
 * Note that it's still up to the caller to close the heap relation.
 
264
 */
 
265
void
 
266
systable_endscan(SysScanDesc sysscan)
 
267
{
 
268
        if (sysscan->irel)
 
269
        {
 
270
                index_endscan(sysscan->iscan);
 
271
                index_close(sysscan->irel);
 
272
        }
 
273
        else
 
274
                heap_endscan(sysscan->scan);
 
275
 
 
276
        pfree(sysscan);
 
277
}