summaryrefslogtreecommitdiff
path: root/src/backend/access/gist/giststrat.c
blob: c6212edf109c0650d76828d4cca75eba603d6e50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*-------------------------------------------------------------------------
 *
 * giststrat.c--
 *    strategy map data for GiSTs.
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *    /usr/local/devel/pglite/cvs/src/backend/access/gist/giststrat.c,v 1.4 1995/06/14 00:10:05 jolly Exp
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"
 
#include "catalog/pg_attribute.h"
#include "access/attnum.h"
#include "nodes/pg_list.h"
#include "access/tupdesc.h"
#include "storage/fd.h"
#include "catalog/pg_am.h"
#include "catalog/pg_class.h"
#include "nodes/nodes.h"
#include "rewrite/prs2lock.h"
#include "access/skey.h"
#include "access/strat.h"
#include "utils/rel.h"

#include "storage/off.h"

#include "storage/block.h"
 
#include "storage/itemid.h"
#include "storage/item.h"  
#include "storage/buf.h" 
#include "storage/bufpage.h"
#include "access/gist.h"

#include "access/istrat.h"

/*
 *  Note:  negate, commute, and negatecommute all assume that operators are
 *	   ordered as follows in the strategy map:
 *
 *	contains, contained-by
 *
 *  The negate, commute, and negatecommute arrays are used by the planner
 *  to plan indexed scans over data that appears in the qualificiation in
 *  a boolean negation, or whose operands appear in the wrong order.  For
 *  example, if the operator "<%" means "contains", and the user says
 *
 *	where not rel.box <% "(10,10,20,20)"::box
 *
 *  the planner can plan an index scan by noting that GiST indices have
 *  an operator in their operator class for negating <%.
 *
 *  Similarly, if the user says something like
 *
 *	where "(10,10,20,20)"::box <% rel.box
 *
 *  the planner can see that the GiST index on rel.box has an operator in
 *  its opclass for commuting <%, and plan the scan using that operator.
 *  This added complexity in the access methods makes the planner a lot easier
 *  to write.
 */

/* if a op b, what operator tells us if (not a op b)? */
static StrategyNumber	GISTNegate[GISTNStrategies] = {
    InvalidStrategy,
    InvalidStrategy,
    InvalidStrategy
    };

/* if a op_1 b, what is the operator op_2 such that b op_2 a? */
static StrategyNumber	GISTCommute[GISTNStrategies] = {
    InvalidStrategy,
    InvalidStrategy,
    InvalidStrategy
    };

/* if a op_1 b, what is the operator op_2 such that (b !op_2 a)? */
static StrategyNumber	GISTNegateCommute[GISTNStrategies] = {
    InvalidStrategy,
    InvalidStrategy,
    InvalidStrategy
    };

/*
 * GiSTs do not currently support TermData (see rtree/rtstrat.c for 
 * discussion of
 * TermData) -- such logic must be encoded in the user's Consistent function.
 */

/*
 *  If you were sufficiently attentive to detail, you would go through
 *  the ExpressionData pain above for every one of the strategies
 *  we defined.  I am not.  Now we declare the StrategyEvaluationData
 *  structure that gets shipped around to help the planner and the access
 *  method decide what sort of scan it should do, based on (a) what the
 *  user asked for, (b) what operators are defined for a particular opclass,
 *  and (c) the reams of information we supplied above.
 *
 *  The idea of all of this initialized data is to make life easier on the
 *  user when he defines a new operator class to use this access method.
 *  By filling in all the data, we let him get away with leaving holes in his
 *  operator class, and still let him use the index.  The added complexity
 *  in the access methods just isn't worth the trouble, though.
 */

static StrategyEvaluationData GISTEvaluationData = {
    GISTNStrategies,				/* # of strategies */
    (StrategyTransformMap) GISTNegate,	/* how to do (not qual) */
    (StrategyTransformMap) GISTCommute,	/* how to swap operands */
    (StrategyTransformMap) GISTNegateCommute,	/* how to do both */
    { NULL }
};

StrategyNumber
RelationGetGISTStrategy(Relation r,
		      AttrNumber attnum,
		      RegProcedure proc)
{
    return (RelationGetStrategy(r, attnum, &GISTEvaluationData, proc));
}

bool
RelationInvokeGISTStrategy(Relation r,
			 AttrNumber attnum,
			 StrategyNumber s,
			 Datum left,
			 Datum right)
{
    return (RelationInvokeStrategy(r, &GISTEvaluationData, attnum, s,
				   left, right));
}