Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/gist_private.h"
00018 #include "access/gistscan.h"
00019 #include "access/relscan.h"
00020 #include "utils/memutils.h"
00021 #include "utils/rel.h"
00022
00023
00024
00025
00026
00027
00028 static int
00029 GISTSearchTreeItemComparator(const RBNode *a, const RBNode *b, void *arg)
00030 {
00031 const GISTSearchTreeItem *sa = (const GISTSearchTreeItem *) a;
00032 const GISTSearchTreeItem *sb = (const GISTSearchTreeItem *) b;
00033 IndexScanDesc scan = (IndexScanDesc) arg;
00034 int i;
00035
00036
00037 for (i = 0; i < scan->numberOfOrderBys; i++)
00038 {
00039 if (sa->distances[i] != sb->distances[i])
00040 return (sa->distances[i] > sb->distances[i]) ? 1 : -1;
00041 }
00042
00043 return 0;
00044 }
00045
00046 static void
00047 GISTSearchTreeItemCombiner(RBNode *existing, const RBNode *newrb, void *arg)
00048 {
00049 GISTSearchTreeItem *scurrent = (GISTSearchTreeItem *) existing;
00050 const GISTSearchTreeItem *snew = (const GISTSearchTreeItem *) newrb;
00051 GISTSearchItem *newitem = snew->head;
00052
00053
00054 Assert(newitem && newitem->next == NULL);
00055
00056
00057
00058
00059
00060
00061
00062 if (GISTSearchItemIsHeap(*newitem))
00063 {
00064 newitem->next = scurrent->head;
00065 scurrent->head = newitem;
00066 if (scurrent->lastHeap == NULL)
00067 scurrent->lastHeap = newitem;
00068 }
00069 else if (scurrent->lastHeap == NULL)
00070 {
00071 newitem->next = scurrent->head;
00072 scurrent->head = newitem;
00073 }
00074 else
00075 {
00076 newitem->next = scurrent->lastHeap->next;
00077 scurrent->lastHeap->next = newitem;
00078 }
00079 }
00080
00081 static RBNode *
00082 GISTSearchTreeItemAllocator(void *arg)
00083 {
00084 IndexScanDesc scan = (IndexScanDesc) arg;
00085
00086 return palloc(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys);
00087 }
00088
00089 static void
00090 GISTSearchTreeItemDeleter(RBNode *rb, void *arg)
00091 {
00092 pfree(rb);
00093 }
00094
00095
00096
00097
00098
00099
00100 Datum
00101 gistbeginscan(PG_FUNCTION_ARGS)
00102 {
00103 Relation r = (Relation) PG_GETARG_POINTER(0);
00104 int nkeys = PG_GETARG_INT32(1);
00105 int norderbys = PG_GETARG_INT32(2);
00106 IndexScanDesc scan;
00107 GISTSTATE *giststate;
00108 GISTScanOpaque so;
00109 MemoryContext oldCxt;
00110
00111 scan = RelationGetIndexScan(r, nkeys, norderbys);
00112
00113
00114 giststate = initGISTstate(scan->indexRelation);
00115
00116
00117
00118
00119
00120 oldCxt = MemoryContextSwitchTo(giststate->scanCxt);
00121
00122
00123 so = (GISTScanOpaque) palloc0(sizeof(GISTScanOpaqueData));
00124 so->giststate = giststate;
00125 giststate->tempCxt = createTempGistContext();
00126 so->queue = NULL;
00127 so->queueCxt = giststate->scanCxt;
00128
00129
00130 so->tmpTreeItem = palloc(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys);
00131 so->distances = palloc(sizeof(double) * scan->numberOfOrderBys);
00132 so->qual_ok = true;
00133
00134 scan->opaque = so;
00135
00136 MemoryContextSwitchTo(oldCxt);
00137
00138 PG_RETURN_POINTER(scan);
00139 }
00140
00141 Datum
00142 gistrescan(PG_FUNCTION_ARGS)
00143 {
00144 IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
00145 ScanKey key = (ScanKey) PG_GETARG_POINTER(1);
00146 ScanKey orderbys = (ScanKey) PG_GETARG_POINTER(3);
00147
00148
00149 GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
00150 bool first_time;
00151 int i;
00152 MemoryContext oldCxt;
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 if (so->queue == NULL)
00167 {
00168
00169 Assert(so->queueCxt == so->giststate->scanCxt);
00170 first_time = true;
00171 }
00172 else if (so->queueCxt == so->giststate->scanCxt)
00173 {
00174
00175 so->queueCxt = AllocSetContextCreate(so->giststate->scanCxt,
00176 "GiST queue context",
00177 ALLOCSET_DEFAULT_MINSIZE,
00178 ALLOCSET_DEFAULT_INITSIZE,
00179 ALLOCSET_DEFAULT_MAXSIZE);
00180 first_time = false;
00181 }
00182 else
00183 {
00184
00185 MemoryContextReset(so->queueCxt);
00186 first_time = false;
00187 }
00188
00189
00190 oldCxt = MemoryContextSwitchTo(so->queueCxt);
00191 so->queue = rb_create(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys,
00192 GISTSearchTreeItemComparator,
00193 GISTSearchTreeItemCombiner,
00194 GISTSearchTreeItemAllocator,
00195 GISTSearchTreeItemDeleter,
00196 scan);
00197 MemoryContextSwitchTo(oldCxt);
00198
00199 so->curTreeItem = NULL;
00200 so->firstCall = true;
00201
00202
00203 if (key && scan->numberOfKeys > 0)
00204 {
00205
00206
00207
00208
00209
00210 if (!first_time)
00211 {
00212 for (i = 0; i < scan->numberOfKeys; i++)
00213 {
00214 ScanKey skey = scan->keyData + i;
00215
00216 so->giststate->consistentFn[skey->sk_attno - 1].fn_extra =
00217 skey->sk_func.fn_extra;
00218 }
00219 }
00220
00221 memmove(scan->keyData, key,
00222 scan->numberOfKeys * sizeof(ScanKeyData));
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 so->qual_ok = true;
00240
00241 for (i = 0; i < scan->numberOfKeys; i++)
00242 {
00243 ScanKey skey = scan->keyData + i;
00244
00245 skey->sk_func = so->giststate->consistentFn[skey->sk_attno - 1];
00246
00247 if (skey->sk_flags & SK_ISNULL)
00248 {
00249 if (!(skey->sk_flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL)))
00250 so->qual_ok = false;
00251 }
00252 }
00253 }
00254
00255
00256 if (orderbys && scan->numberOfOrderBys > 0)
00257 {
00258
00259 if (!first_time)
00260 {
00261 for (i = 0; i < scan->numberOfOrderBys; i++)
00262 {
00263 ScanKey skey = scan->orderByData + i;
00264
00265 so->giststate->distanceFn[skey->sk_attno - 1].fn_extra =
00266 skey->sk_func.fn_extra;
00267 }
00268 }
00269
00270 memmove(scan->orderByData, orderbys,
00271 scan->numberOfOrderBys * sizeof(ScanKeyData));
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 for (i = 0; i < scan->numberOfOrderBys; i++)
00283 {
00284 ScanKey skey = scan->orderByData + i;
00285
00286 skey->sk_func = so->giststate->distanceFn[skey->sk_attno - 1];
00287
00288
00289 if (!OidIsValid(skey->sk_func.fn_oid))
00290 elog(ERROR, "missing support function %d for attribute %d of index \"%s\"",
00291 GIST_DISTANCE_PROC, skey->sk_attno,
00292 RelationGetRelationName(scan->indexRelation));
00293 }
00294 }
00295
00296 PG_RETURN_VOID();
00297 }
00298
00299 Datum
00300 gistmarkpos(PG_FUNCTION_ARGS)
00301 {
00302 elog(ERROR, "GiST does not support mark/restore");
00303 PG_RETURN_VOID();
00304 }
00305
00306 Datum
00307 gistrestrpos(PG_FUNCTION_ARGS)
00308 {
00309 elog(ERROR, "GiST does not support mark/restore");
00310 PG_RETURN_VOID();
00311 }
00312
00313 Datum
00314 gistendscan(PG_FUNCTION_ARGS)
00315 {
00316 IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
00317 GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
00318
00319
00320
00321
00322
00323 freeGISTstate(so->giststate);
00324
00325 PG_RETURN_VOID();
00326 }