+ linkend="xindex-hash-support-table">.
-
-
-
Operator Classes
+
+
Hash Support Functions
+ Hash
+
+
+ |
+ Operation
+ Support Number
+
+
+
+ |
+ compute the hash value for a key
+ 1
+
+
+
+
- The next table of interest is pg_opclass. This table
- defines operator class names and input data types for each of the operator
- classes supported by a given index access method. The same class name
- can be used for several different access methods (for example, both B-tree
- and hash access methods have operator classes named
- oid_ops), but a separate
- pg_opclass row must appear for each access method.
- The OID of the pg_opclass row is
- used as a foreign
- key in other tables to associate specific operators and support routines
- with the operator class.
+ R-tree indexes require three support functions,
+ as shown in .
- You need to add a row with your operator class name (for example,
- complex_abs_ops) to
- pg_opclass:
-
-INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
- VALUES (
- (SELECT oid FROM pg_am WHERE amname = 'btree'),
- 'complex_abs_ops',
- (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
- 1, -- UID of superuser is hardwired to 1 as of PG 7.3
- (SELECT oid FROM pg_type WHERE typname = 'complex'),
- true,
- 0);
-
-SELECT oid, *
- FROM pg_opclass
- WHERE opcname = 'complex_abs_ops';
-
- oid | opcamid | opcname | opcnamespace | opcowner | opcintype | opcdefault | opckeytype
---------+---------+-----------------+--------------+----------+-----------+------------+------------
- 277975 | 403 | complex_abs_ops | 11 | 1 | 277946 | t | 0
-(1 row)
-
-
- Note that the OID for your pg_opclass row will
- be different! Don't worry about this though. We'll get this number
- from the system later just like we got the OID of the type here.
-
+
+
R-tree Support Functions
+ R-tree
+
+
+ |
+ Operation
+ Support Number
+
+
+
+ |
+ union
+ 1
+
+ |
+ intersection
+ 2
+
+ |
+ size
+ 3
+
+
+
+
- The above example assumes that you want to make this new operator class the
- default B-tree operator class for the complex data type.
- If you don't, just set opcdefault to false instead.
- opckeytype is not described here; it should always
- be zero for B-tree operator classes.
+ GiST indexes require seven support functions,
+ as shown in .
+
+
+
GiST Support Functions
+ GiST
+
+
+ |
+ Operation
+ Support Number
+
+
+
+ |
+ consistent
+ 1
+
+ |
+ union
+ 2
+
+ |
+ compress
+ 3
+
+ |
+ decompress
+ 4
+
+ |
+ penalty
+ 5
+
+ |
+ picksplit
+ 6
+
+ |
+ equal
+ 7
+
+
+
+
+
Creating the Operators and Support Routines
- So now we have an access method and an operator class.
- We still need a set of operators. The procedure for
+ Now that we have seen the ideas, here is the promised example
+ of creating a new operator class. First, we need a set of operators.
+ The procedure for
defining operators was discussed in .
For the complex_abs_ops operator class on B-trees,
the operators we require are:
In practice, all operators defined as index access method
strategies must return type boolean, since they must
appear at the top level of a WHERE> clause to be used with an index.
- (On the other hand, the support function returns whatever the
- particular access method expects -- in this case, a signed
- integer.)
+ (On the other hand, support functions return whatever the
+ particular access method expects -- in the case of the comparison
+ function for B-trees, a signed integer.)
- The final routine in the file is the support routine
- mentioned when we discussed the amsupport> column of the
- pg_am table. We will use this later on. For
- now, ignore it.
-
-
Now we are ready to define the operators:
- The next step is to add entries for these operators to
- the pg_amop relation. To do this,
- we'll need the OIDs of the operators we just
- defined. We'll look up the names of all the operators that take
- two operands of type complex, and pick ours out:
-
-
-SELECT o.oid AS opoid, o.oprname
- INTO TEMP TABLE complex_ops_tmp
- FROM pg_operator o, pg_type t
- WHERE o.oprleft = t.oid and o.oprright = t.oid
- and t.typname = 'complex';
-
- opoid | oprname
---------+---------
- 277963 | +
- 277970 | <
- 277971 | <=
- 277972 | =
- 277973 | >=
- 277974 | >
-(6 rows)
-
-
- (Again, some of your OID numbers will almost
- certainly be different.) The operators we are interested in are those
- with OIDs 277970 through 277974. The values you
- get will probably be different, and you should substitute them for the
- values below. We will do this with a select statement.
-
-
- Now we are ready to insert entries into pg_amop for
- our new operator class. These entries must associate the correct
- B-tree strategy numbers with each of the operators we need.
- The command to insert the less-than operator looks like:
+ The next step is the registration of the comparison support
+ routine required by B-trees. The C code that implements this
+ is in the same file that contains the operator procedures:
-INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
- SELECT opcl.oid, 1, false, c.opoid
- FROM pg_opclass opcl, complex_ops_tmp c
- WHERE
- opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
- opcname = 'complex_abs_ops' AND
- c.oprname = '<';
+CREATE FUNCTION complex_abs_cmp(complex, complex)
+ RETURNS integer
+ AS 'PGROOT/src/tutorial/complex'
+ LANGUAGE C;
-
- Now do this for the other operators substituting for the 1> in the
- second line above and the <> in the last line. Note the order:
- less than> is 1, less than or equal> is 2,
- equal> is 3, greater than or equal
is 4, and
- greater than
is 5.
+
+
+
+
Creating the Operator Class
- The field amopreqcheck is not discussed here; it
- should always be false for B-tree operators.
+ Now that we have the required operators and support routine,
+ we can finally create the operator class:
+
+CREATE OPERATOR CLASS complex_abs_ops
+ DEFAULT FOR TYPE complex USING btree AS
+ OPERATOR 1 < ,
+ OPERATOR 2 <= ,
+ OPERATOR 3 = ,
+ OPERATOR 4 >= ,
+ OPERATOR 5 > ,
+ FUNCTION 1 complex_abs_cmp(complex, complex);
+
- The final step is the registration of the support routine
previously
- described in our discussion of pg_am. The
- OID of this support routine is stored in the
- pg_amproc table, keyed by the operator class
- OID and the support routine number.
+ And we're done! (Whew.) It should now be possible to create
+ and use B-tree indexes on complex columns.
- First, we need to register the function in
-
PostgreSQL (recall that we put the
- C code that implements this routine in the bottom of
- the file in which we implemented the operator routines):
-
+ We could have written the operator entries more verbosely, as in
-CREATE FUNCTION complex_abs_cmp(complex, complex)
- RETURNS integer
- AS 'PGROOT/src/tutorial/complex'
- LANGUAGE C;
-
-SELECT oid, proname FROM pg_proc
- WHERE proname = 'complex_abs_cmp';
-
- oid | proname
---------+-----------------
- 277997 | complex_abs_cmp
-(1 row)
+ OPERATOR 1 < (complex, complex) ,
+ but there is no need to do so when the operators take the same datatype
+ we are defining the operator class for.
+
- (Again, your OID number will probably be different.)
+ The above example assumes that you want to make this new operator class the
+ default B-tree operator class for the complex data type.
+ If you don't, just leave out the word DEFAULT>.
+
+
+
+
Special Features of Operator Classes
- We can add the new row as follows:
+ There are two special features of operator classes that we have
+ not discussed yet, mainly because they are not very useful
+ with the default B-tree index access method.
+
+ Normally, declaring an operator as a member of an operator class means
+ that the index access method can retrieve exactly the set of rows
+ that satisfy a WHERE condition using the operator. For example,
-INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
- SELECT opcl.oid, 1, p.oid
- FROM pg_opclass opcl, pg_proc p
- WHERE
- opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
- opcname = 'complex_abs_ops' AND
- p.proname = 'complex_abs_cmp';
+SELECT * FROM table WHERE integer_column < 4;
+ can be satisfied exactly by a B-tree index on the integer column.
+ But there are cases where an index is useful as an inexact guide to
+ the matching rows. For example, if an R-tree index stores only
+ bounding boxes for objects, then it cannot exactly satisfy a WHERE
+ condition that tests overlap between nonrectangular objects such as
+ polygons. Yet we could use the index to find objects whose bounding
+ box overlaps the bounding box of the target object, and then do the
+ exact overlap test only on the objects found by the index. If this
+ scenario applies, the index is said to be lossy> for the
+ operator, and we mark the OPERATOR> clause in the
+ CREATE OPERATOR CLASS> command with RECHECK>.
+ RECHECK> is valid if the index is guaranteed to return
+ all the required tuples, plus perhaps some additional tuples, which
+ can be eliminated by performing the original operator comparison.
- And we're done! (Whew.) It should now be possible to create
- and use B-tree indexes on complex columns.
+ Consider again the situation where we are storing in the index only
+ the bounding box of a complex object such as a polygon. In this
+ case there's not much value in storing the whole polygon in the index
+ entry --- we may as well store just a simpler object of type
+ box>. This situation is expressed by the STORAGE>
+ option in CREATE OPERATOR CLASS>: we'd write something like
+
+CREATE OPERATOR CLASS polygon_ops
+ DEFAULT FOR TYPE polygon USING gist AS
+ ...
+ STORAGE box;
+
+
+ At present, only the GiST access method supports a
+ STORAGE> type that's different from the column datatype.
+ The GiST compress> and decompress> support
+ routines must deal with datatype conversion when STORAGE>
+ is used.