~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to contrib/rtree_gist/rtree_gist.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
 * rtree_gist.c
 
4
 *        pg_amproc entries for GiSTs over 2-D boxes.
 
5
 * This gives R-tree behavior, with Guttman's poly-time split algorithm.
 
6
 *
 
7
 *
 
8
 *
 
9
 * IDENTIFICATION
 
10
 *      $PostgreSQL: pgsql/contrib/rtree_gist/rtree_gist.c,v 1.10 2004-08-29 05:06:37 momjian Exp $
 
11
 *
 
12
 *-------------------------------------------------------------------------
 
13
 */
 
14
#include "postgres.h"
 
15
 
 
16
#include "access/gist.h"
 
17
#include "access/itup.h"
 
18
#include "access/rtree.h"
 
19
#include "utils/geo_decls.h"
 
20
 
 
21
typedef Datum (*RDF) (PG_FUNCTION_ARGS);
 
22
typedef Datum (*BINARY_UNION) (Datum, Datum, int *);
 
23
typedef float (*SIZE_BOX) (Datum);
 
24
 
 
25
/*
 
26
** box ops
 
27
*/
 
28
PG_FUNCTION_INFO_V1(gbox_compress);
 
29
PG_FUNCTION_INFO_V1(gbox_union);
 
30
PG_FUNCTION_INFO_V1(gbox_picksplit);
 
31
PG_FUNCTION_INFO_V1(gbox_consistent);
 
32
PG_FUNCTION_INFO_V1(gbox_penalty);
 
33
PG_FUNCTION_INFO_V1(gbox_same);
 
34
 
 
35
Datum           gbox_compress(PG_FUNCTION_ARGS);
 
36
Datum           gbox_union(PG_FUNCTION_ARGS);
 
37
Datum           gbox_picksplit(PG_FUNCTION_ARGS);
 
38
Datum           gbox_consistent(PG_FUNCTION_ARGS);
 
39
Datum           gbox_penalty(PG_FUNCTION_ARGS);
 
40
Datum           gbox_same(PG_FUNCTION_ARGS);
 
41
 
 
42
static bool gbox_leaf_consistent(BOX *key, BOX *query, StrategyNumber strategy);
 
43
static float size_box(Datum box);
 
44
 
 
45
/*
 
46
** Polygon ops
 
47
*/
 
48
PG_FUNCTION_INFO_V1(gpoly_compress);
 
49
PG_FUNCTION_INFO_V1(gpoly_consistent);
 
50
 
 
51
Datum           gpoly_compress(PG_FUNCTION_ARGS);
 
52
Datum           gpoly_consistent(PG_FUNCTION_ARGS);
 
53
 
 
54
/*
 
55
** Common rtree-function (for all ops)
 
56
*/
 
57
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy);
 
58
 
 
59
PG_FUNCTION_INFO_V1(rtree_decompress);
 
60
 
 
61
Datum           rtree_decompress(PG_FUNCTION_ARGS);
 
62
 
 
63
/**************************************************
 
64
 * Box ops
 
65
 **************************************************/
 
66
 
 
67
/*
 
68
** The GiST Consistent method for boxes
 
69
** Should return false if for all data items x below entry,
 
70
** the predicate x op query == FALSE, where op is the oper
 
71
** corresponding to strategy in the pg_amop table.
 
72
*/
 
73
Datum
 
74
gbox_consistent(PG_FUNCTION_ARGS)
 
75
{
 
76
        GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 
77
        BOX                *query = (BOX *) PG_GETARG_POINTER(1);
 
78
        StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
 
79
 
 
80
        /*
 
81
         * * if entry is not leaf, use gbox_internal_consistent, * else use
 
82
         * gbox_leaf_consistent
 
83
         */
 
84
        if (!(DatumGetPointer(entry->key) != NULL && query))
 
85
                PG_RETURN_BOOL(FALSE);
 
86
 
 
87
        if (GIST_LEAF(entry))
 
88
                PG_RETURN_BOOL(gbox_leaf_consistent((BOX *) DatumGetPointer(entry->key), query, strategy));
 
89
        else
 
90
                PG_RETURN_BOOL(rtree_internal_consistent((BOX *) DatumGetPointer(entry->key), query, strategy));
 
91
}
 
92
 
 
93
 
 
94
/*
 
95
** The GiST Union method for boxes
 
96
** returns the minimal bounding box that encloses all the entries in entryvec
 
97
*/
 
98
Datum
 
99
gbox_union(PG_FUNCTION_ARGS)
 
100
{
 
101
        GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
 
102
        int                *sizep = (int *) PG_GETARG_POINTER(1);
 
103
        int                     numranges,
 
104
                                i;
 
105
        BOX                *cur,
 
106
                           *pageunion;
 
107
 
 
108
        numranges = entryvec->n;
 
109
        pageunion = (BOX *) palloc(sizeof(BOX));
 
110
        cur = DatumGetBoxP(entryvec->vector[0].key);
 
111
        memcpy((void *) pageunion, (void *) cur, sizeof(BOX));
 
112
 
 
113
        for (i = 1; i < numranges; i++)
 
114
        {
 
115
                cur = DatumGetBoxP(entryvec->vector[i].key);
 
116
                if (pageunion->high.x < cur->high.x)
 
117
                        pageunion->high.x = cur->high.x;
 
118
                if (pageunion->low.x > cur->low.x)
 
119
                        pageunion->low.x = cur->low.x;
 
120
                if (pageunion->high.y < cur->high.y)
 
121
                        pageunion->high.y = cur->high.y;
 
122
                if (pageunion->low.y > cur->low.y)
 
123
                        pageunion->low.y = cur->low.y;
 
124
        }
 
125
        *sizep = sizeof(BOX);
 
126
 
 
127
        PG_RETURN_POINTER(pageunion);
 
128
}
 
129
 
 
130
/*
 
131
** GiST Compress methods for boxes
 
132
** do not do anything.
 
133
*/
 
134
Datum
 
135
gbox_compress(PG_FUNCTION_ARGS)
 
136
{
 
137
        PG_RETURN_POINTER(PG_GETARG_POINTER(0));
 
138
}
 
139
 
 
140
/*
 
141
** The GiST Penalty method for boxes
 
142
** As in the R-tree paper, we use change in area as our penalty metric
 
143
*/
 
144
Datum
 
145
gbox_penalty(PG_FUNCTION_ARGS)
 
146
{
 
147
        GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
 
148
        GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
 
149
        float      *result = (float *) PG_GETARG_POINTER(2);
 
150
        Datum           ud;
 
151
        float           tmp1;
 
152
 
 
153
        ud = DirectFunctionCall2(rt_box_union, origentry->key, newentry->key);
 
154
        tmp1 = size_box(ud);
 
155
        if (DatumGetPointer(ud) != NULL)
 
156
                pfree(DatumGetPointer(ud));
 
157
 
 
158
        *result = tmp1 - size_box(origentry->key);
 
159
        PG_RETURN_POINTER(result);
 
160
}
 
161
 
 
162
typedef struct
 
163
{
 
164
        BOX                *key;
 
165
        int                     pos;
 
166
}       KBsort;
 
167
 
 
168
static int
 
169
compare_KB(const void *a, const void *b)
 
170
{
 
171
        BOX                *abox = ((KBsort *) a)->key;
 
172
        BOX                *bbox = ((KBsort *) b)->key;
 
173
        float           sa = (abox->high.x - abox->low.x) * (abox->high.y - abox->low.y);
 
174
        float           sb = (bbox->high.x - bbox->low.x) * (bbox->high.y - bbox->low.y);
 
175
 
 
176
        if (sa == sb)
 
177
                return 0;
 
178
        return (sa > sb) ? 1 : -1;
 
179
}
 
180
 
 
181
/*
 
182
** The GiST PickSplit method
 
183
** New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree',
 
184
** C.H.Ang and T.C.Tan
 
185
*/
 
186
Datum
 
187
gbox_picksplit(PG_FUNCTION_ARGS)
 
188
{
 
189
        GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
 
190
        GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
 
191
        OffsetNumber i;
 
192
        OffsetNumber *listL,
 
193
                           *listR,
 
194
                           *listB,
 
195
                           *listT;
 
196
        BOX                *unionL,
 
197
                           *unionR,
 
198
                           *unionB,
 
199
                           *unionT;
 
200
        int                     posL,
 
201
                                posR,
 
202
                                posB,
 
203
                                posT;
 
204
        BOX                     pageunion;
 
205
        BOX                *cur;
 
206
        char            direction = ' ';
 
207
        bool            allisequal = true;
 
208
        OffsetNumber maxoff;
 
209
        int                     nbytes;
 
210
 
 
211
        posL = posR = posB = posT = 0;
 
212
        maxoff = entryvec->n - 1;
 
213
 
 
214
        cur = DatumGetBoxP(entryvec->vector[FirstOffsetNumber].key);
 
215
        memcpy((void *) &pageunion, (void *) cur, sizeof(BOX));
 
216
 
 
217
        /* find MBR */
 
218
        for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff; i = OffsetNumberNext(i))
 
219
        {
 
220
                cur = DatumGetBoxP(entryvec->vector[i].key);
 
221
                if (allisequal == true && (
 
222
                                                                   pageunion.high.x != cur->high.x ||
 
223
                                                                   pageunion.high.y != cur->high.y ||
 
224
                                                                   pageunion.low.x != cur->low.x ||
 
225
                                                                   pageunion.low.y != cur->low.y
 
226
                                                                   ))
 
227
                        allisequal = false;
 
228
 
 
229
                if (pageunion.high.x < cur->high.x)
 
230
                        pageunion.high.x = cur->high.x;
 
231
                if (pageunion.low.x > cur->low.x)
 
232
                        pageunion.low.x = cur->low.x;
 
233
                if (pageunion.high.y < cur->high.y)
 
234
                        pageunion.high.y = cur->high.y;
 
235
                if (pageunion.low.y > cur->low.y)
 
236
                        pageunion.low.y = cur->low.y;
 
237
        }
 
238
 
 
239
        nbytes = (maxoff + 2) * sizeof(OffsetNumber);
 
240
        listL = (OffsetNumber *) palloc(nbytes);
 
241
        listR = (OffsetNumber *) palloc(nbytes);
 
242
        unionL = (BOX *) palloc(sizeof(BOX));
 
243
        unionR = (BOX *) palloc(sizeof(BOX));
 
244
        if (allisequal)
 
245
        {
 
246
                cur = DatumGetBoxP(entryvec->vector[OffsetNumberNext(FirstOffsetNumber)].key);
 
247
                if (memcmp((void *) cur, (void *) &pageunion, sizeof(BOX)) == 0)
 
248
                {
 
249
                        v->spl_left = listL;
 
250
                        v->spl_right = listR;
 
251
                        v->spl_nleft = v->spl_nright = 0;
 
252
                        memcpy((void *) unionL, (void *) &pageunion, sizeof(BOX));
 
253
                        memcpy((void *) unionR, (void *) &pageunion, sizeof(BOX));
 
254
 
 
255
                        for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
 
256
                        {
 
257
                                if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
 
258
                                {
 
259
                                        v->spl_left[v->spl_nleft] = i;
 
260
                                        v->spl_nleft++;
 
261
                                }
 
262
                                else
 
263
                                {
 
264
                                        v->spl_right[v->spl_nright] = i;
 
265
                                        v->spl_nright++;
 
266
                                }
 
267
                        }
 
268
                        v->spl_ldatum = BoxPGetDatum(unionL);
 
269
                        v->spl_rdatum = BoxPGetDatum(unionR);
 
270
 
 
271
                        PG_RETURN_POINTER(v);
 
272
                }
 
273
        }
 
274
 
 
275
        listB = (OffsetNumber *) palloc(nbytes);
 
276
        listT = (OffsetNumber *) palloc(nbytes);
 
277
        unionB = (BOX *) palloc(sizeof(BOX));
 
278
        unionT = (BOX *) palloc(sizeof(BOX));
 
279
 
 
280
#define ADDLIST( list, unionD, pos, num ) do { \
 
281
        if ( pos ) { \
 
282
                if ( unionD->high.x < cur->high.x ) unionD->high.x      = cur->high.x; \
 
283
                if ( unionD->low.x      > cur->low.x  ) unionD->low.x   = cur->low.x; \
 
284
                if ( unionD->high.y < cur->high.y ) unionD->high.y      = cur->high.y; \
 
285
                if ( unionD->low.y      > cur->low.y  ) unionD->low.y   = cur->low.y; \
 
286
        } else { \
 
287
                        memcpy( (void*)unionD, (void*) cur, sizeof( BOX ) );  \
 
288
        } \
 
289
        list[pos] = num; \
 
290
        (pos)++; \
 
291
} while(0)
 
292
 
 
293
        for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
 
294
        {
 
295
                cur = DatumGetBoxP(entryvec->vector[i].key);
 
296
                if (cur->low.x - pageunion.low.x < pageunion.high.x - cur->high.x)
 
297
                        ADDLIST(listL, unionL, posL, i);
 
298
                else
 
299
                        ADDLIST(listR, unionR, posR, i);
 
300
                if (cur->low.y - pageunion.low.y < pageunion.high.y - cur->high.y)
 
301
                        ADDLIST(listB, unionB, posB, i);
 
302
                else
 
303
                        ADDLIST(listT, unionT, posT, i);
 
304
        }
 
305
 
 
306
        /* bad disposition, sort by ascending and resplit */
 
307
        if ((posR == 0 || posL == 0) && (posT == 0 || posB == 0))
 
308
        {
 
309
                KBsort     *arr = (KBsort *) palloc(sizeof(KBsort) * maxoff);
 
310
 
 
311
                posL = posR = posB = posT = 0;
 
312
                for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
 
313
                {
 
314
                        arr[i - 1].key = DatumGetBoxP(entryvec->vector[i].key);
 
315
                        arr[i - 1].pos = i;
 
316
                }
 
317
                qsort(arr, maxoff, sizeof(KBsort), compare_KB);
 
318
                for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
 
319
                {
 
320
                        cur = arr[i - 1].key;
 
321
                        if (cur->low.x - pageunion.low.x < pageunion.high.x - cur->high.x)
 
322
                                ADDLIST(listL, unionL, posL, arr[i - 1].pos);
 
323
                        else if (cur->low.x - pageunion.low.x == pageunion.high.x - cur->high.x)
 
324
                        {
 
325
                                if (posL > posR)
 
326
                                        ADDLIST(listR, unionR, posR, arr[i - 1].pos);
 
327
                                else
 
328
                                        ADDLIST(listL, unionL, posL, arr[i - 1].pos);
 
329
                        }
 
330
                        else
 
331
                                ADDLIST(listR, unionR, posR, arr[i - 1].pos);
 
332
 
 
333
                        if (cur->low.y - pageunion.low.y < pageunion.high.y - cur->high.y)
 
334
                                ADDLIST(listB, unionB, posB, arr[i - 1].pos);
 
335
                        else if (cur->low.y - pageunion.low.y == pageunion.high.y - cur->high.y)
 
336
                        {
 
337
                                if (posB > posT)
 
338
                                        ADDLIST(listT, unionT, posT, arr[i - 1].pos);
 
339
                                else
 
340
                                        ADDLIST(listB, unionB, posB, arr[i - 1].pos);
 
341
                        }
 
342
                        else
 
343
                                ADDLIST(listT, unionT, posT, arr[i - 1].pos);
 
344
                }
 
345
                pfree(arr);
 
346
        }
 
347
 
 
348
        /* which split more optimal? */
 
349
        if (Max(posL, posR) < Max(posB, posT))
 
350
                direction = 'x';
 
351
        else if (Max(posL, posR) > Max(posB, posT))
 
352
                direction = 'y';
 
353
        else
 
354
        {
 
355
                Datum           interLR = DirectFunctionCall2(rt_box_inter,
 
356
                                                                                                  BoxPGetDatum(unionL),
 
357
                                                                                                  BoxPGetDatum(unionR));
 
358
                Datum           interBT = DirectFunctionCall2(rt_box_inter,
 
359
                                                                                                  BoxPGetDatum(unionB),
 
360
                                                                                                  BoxPGetDatum(unionT));
 
361
                float           sizeLR,
 
362
                                        sizeBT;
 
363
 
 
364
                sizeLR = size_box(interLR);
 
365
                sizeBT = size_box(interBT);
 
366
 
 
367
                if (sizeLR < sizeBT)
 
368
                        direction = 'x';
 
369
                else
 
370
                        direction = 'y';
 
371
        }
 
372
 
 
373
        if (direction == 'x')
 
374
        {
 
375
                pfree(unionB);
 
376
                pfree(listB);
 
377
                pfree(unionT);
 
378
                pfree(listT);
 
379
 
 
380
                v->spl_left = listL;
 
381
                v->spl_right = listR;
 
382
                v->spl_nleft = posL;
 
383
                v->spl_nright = posR;
 
384
                v->spl_ldatum = BoxPGetDatum(unionL);
 
385
                v->spl_rdatum = BoxPGetDatum(unionR);
 
386
        }
 
387
        else
 
388
        {
 
389
                pfree(unionR);
 
390
                pfree(listR);
 
391
                pfree(unionL);
 
392
                pfree(listL);
 
393
 
 
394
                v->spl_left = listB;
 
395
                v->spl_right = listT;
 
396
                v->spl_nleft = posB;
 
397
                v->spl_nright = posT;
 
398
                v->spl_ldatum = BoxPGetDatum(unionB);
 
399
                v->spl_rdatum = BoxPGetDatum(unionT);
 
400
        }
 
401
 
 
402
        PG_RETURN_POINTER(v);
 
403
}
 
404
 
 
405
/*
 
406
** Equality method
 
407
*/
 
408
Datum
 
409
gbox_same(PG_FUNCTION_ARGS)
 
410
{
 
411
        BOX                *b1 = (BOX *) PG_GETARG_POINTER(0);
 
412
        BOX                *b2 = (BOX *) PG_GETARG_POINTER(1);
 
413
        bool       *result = (bool *) PG_GETARG_POINTER(2);
 
414
 
 
415
        if (b1 && b2)
 
416
                *result = DatumGetBool(DirectFunctionCall2(box_same, PointerGetDatum(b1), PointerGetDatum(b2)));
 
417
        else
 
418
                *result = (b1 == NULL && b2 == NULL) ? TRUE : FALSE;
 
419
        PG_RETURN_POINTER(result);
 
420
}
 
421
 
 
422
/*
 
423
** SUPPORT ROUTINES for boxes
 
424
*/
 
425
static bool
 
426
gbox_leaf_consistent(BOX *key,
 
427
                                         BOX *query,
 
428
                                         StrategyNumber strategy)
 
429
{
 
430
        bool            retval;
 
431
 
 
432
        switch (strategy)
 
433
        {
 
434
                case RTLeftStrategyNumber:
 
435
                        retval = DatumGetBool(DirectFunctionCall2(box_left, PointerGetDatum(key), PointerGetDatum(query)));
 
436
                        break;
 
437
                case RTOverLeftStrategyNumber:
 
438
                        retval = DatumGetBool(DirectFunctionCall2(box_overleft, PointerGetDatum(key), PointerGetDatum(query)));
 
439
                        break;
 
440
                case RTOverlapStrategyNumber:
 
441
                        retval = DatumGetBool(DirectFunctionCall2(box_overlap, PointerGetDatum(key), PointerGetDatum(query)));
 
442
                        break;
 
443
                case RTOverRightStrategyNumber:
 
444
                        retval = DatumGetBool(DirectFunctionCall2(box_overright, PointerGetDatum(key), PointerGetDatum(query)));
 
445
                        break;
 
446
                case RTRightStrategyNumber:
 
447
                        retval = DatumGetBool(DirectFunctionCall2(box_right, PointerGetDatum(key), PointerGetDatum(query)));
 
448
                        break;
 
449
                case RTSameStrategyNumber:
 
450
                        retval = DatumGetBool(DirectFunctionCall2(box_same, PointerGetDatum(key), PointerGetDatum(query)));
 
451
                        break;
 
452
                case RTContainsStrategyNumber:
 
453
                        retval = DatumGetBool(DirectFunctionCall2(box_contain, PointerGetDatum(key), PointerGetDatum(query)));
 
454
                        break;
 
455
                case RTContainedByStrategyNumber:
 
456
                        retval = DatumGetBool(DirectFunctionCall2(box_contained, PointerGetDatum(key), PointerGetDatum(query)));
 
457
                        break;
 
458
                default:
 
459
                        retval = FALSE;
 
460
        }
 
461
        return (retval);
 
462
}
 
463
 
 
464
static float
 
465
size_box(Datum box)
 
466
{
 
467
        if (DatumGetPointer(box) != NULL)
 
468
        {
 
469
                float           size;
 
470
 
 
471
                DirectFunctionCall2(rt_box_size,
 
472
                                                        box, PointerGetDatum(&size));
 
473
                return size;
 
474
        }
 
475
        else
 
476
                return 0.0;
 
477
}
 
478
 
 
479
/**************************************************
 
480
 * Polygon ops
 
481
 **************************************************/
 
482
 
 
483
Datum
 
484
gpoly_compress(PG_FUNCTION_ARGS)
 
485
{
 
486
        GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 
487
        GISTENTRY  *retval;
 
488
 
 
489
        if (entry->leafkey)
 
490
        {
 
491
                retval = palloc(sizeof(GISTENTRY));
 
492
                if (DatumGetPointer(entry->key) != NULL)
 
493
                {
 
494
                        POLYGON    *in;
 
495
                        BOX                *r;
 
496
 
 
497
                        in = (POLYGON *) PG_DETOAST_DATUM(entry->key);
 
498
                        r = (BOX *) palloc(sizeof(BOX));
 
499
                        memcpy((void *) r, (void *) &(in->boundbox), sizeof(BOX));
 
500
                        if (in != (POLYGON *) DatumGetPointer(entry->key))
 
501
                                pfree(in);
 
502
 
 
503
                        gistentryinit(*retval, PointerGetDatum(r),
 
504
                                                  entry->rel, entry->page,
 
505
                                                  entry->offset, sizeof(BOX), FALSE);
 
506
 
 
507
                }
 
508
                else
 
509
                {
 
510
                        gistentryinit(*retval, (Datum) 0,
 
511
                                                  entry->rel, entry->page,
 
512
                                                  entry->offset, 0, FALSE);
 
513
                }
 
514
        }
 
515
        else
 
516
                retval = entry;
 
517
        PG_RETURN_POINTER(retval);
 
518
}
 
519
 
 
520
Datum
 
521
gpoly_consistent(PG_FUNCTION_ARGS)
 
522
{
 
523
        GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 
524
        POLYGON    *query = (POLYGON *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
 
525
        StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
 
526
        bool            result;
 
527
 
 
528
        /*
 
529
         * * if entry is not leaf, use gbox_internal_consistent, * else use
 
530
         * gbox_leaf_consistent
 
531
         */
 
532
        if (!(DatumGetPointer(entry->key) != NULL && query))
 
533
                PG_RETURN_BOOL(FALSE);
 
534
 
 
535
        result = rtree_internal_consistent((BOX *) DatumGetPointer(entry->key),
 
536
                                                                           &(query->boundbox), strategy);
 
537
 
 
538
        PG_FREE_IF_COPY(query, 1);
 
539
        PG_RETURN_BOOL(result);
 
540
}
 
541
 
 
542
/*****************************************
 
543
 * Common rtree-function (for all ops)
 
544
 *****************************************/
 
545
 
 
546
static bool
 
547
rtree_internal_consistent(BOX *key,
 
548
                                                  BOX *query,
 
549
                                                  StrategyNumber strategy)
 
550
{
 
551
        bool            retval;
 
552
 
 
553
        switch (strategy)
 
554
        {
 
555
                case RTLeftStrategyNumber:
 
556
                case RTOverLeftStrategyNumber:
 
557
                        retval = DatumGetBool(DirectFunctionCall2(box_overleft, PointerGetDatum(key), PointerGetDatum(query)));
 
558
                        break;
 
559
                case RTOverlapStrategyNumber:
 
560
                        retval = DatumGetBool(DirectFunctionCall2(box_overlap, PointerGetDatum(key), PointerGetDatum(query)));
 
561
                        break;
 
562
                case RTOverRightStrategyNumber:
 
563
                case RTRightStrategyNumber:
 
564
                        retval = DatumGetBool(DirectFunctionCall2(box_right, PointerGetDatum(key), PointerGetDatum(query)));
 
565
                        break;
 
566
                case RTSameStrategyNumber:
 
567
                case RTContainsStrategyNumber:
 
568
                        retval = DatumGetBool(DirectFunctionCall2(box_contain, PointerGetDatum(key), PointerGetDatum(query)));
 
569
                        break;
 
570
                case RTContainedByStrategyNumber:
 
571
                        retval = DatumGetBool(DirectFunctionCall2(box_overlap, PointerGetDatum(key), PointerGetDatum(query)));
 
572
                        break;
 
573
                default:
 
574
                        retval = FALSE;
 
575
        }
 
576
        return (retval);
 
577
}
 
578
 
 
579
/*
 
580
** GiST DeCompress methods
 
581
** do not do anything.
 
582
*/
 
583
Datum
 
584
rtree_decompress(PG_FUNCTION_ARGS)
 
585
{
 
586
        PG_RETURN_POINTER(PG_GETARG_POINTER(0));
 
587
}