diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml
index 9fcd9b99da..d3942be6a7 100644
--- a/doc/src/sgml/xindex.sgml
+++ b/doc/src/sgml/xindex.sgml
@@ -1,5 +1,5 @@
@@ -91,11 +91,10 @@ Postgres documentation
SELECT oid FROM pg_am WHERE amname = 'btree';
- +----+
- |oid |
- +----+
- |403 |
- +----+
+ oid
+-----
+ 403
+(1 row)
We will use that SELECT in a WHERE
@@ -210,7 +209,8 @@ SELECT oid FROM pg_am WHERE amname = 'btree';
- The amstrategies entry in pg_am is just the number
+ The amstrategies entry in pg_am
+ is just the number
of strategies defined for the access method in question. The procedures
for less than, less equal, and so on don't appear in
pg_am. Similarly, amsupport
@@ -228,28 +228,28 @@ SELECT oid FROM pg_am WHERE amname = 'btree';
- The next class of interest is pg_opclass. This class exists only to
- associate a name and default type with an oid. In pg_amop, every
- B-tree operator class has a set of procedures, one
- through five, above. Some existing opclasses are int2_ops,
- int4_ops, and oid_ops. You need to add an instance with your
- opclass name (for example, complex_abs_ops) to
+ The next class of interest is pg_opclass. This class
+ exists only to associate an operator class name and perhaps a default type
+ with an operator class oid. Some existing opclasses are int2_ops,
+ int4_ops, and oid_ops. You need to add an
+ instance with your opclass name (for example,
+ complex_abs_ops) to
pg_opclass. The oid of
- this instance is a foreign key in other classes.
+ this instance will be a foreign key in other classes, notably
+ pg_amop.
INSERT INTO pg_opclass (opcname, opcdeftype)
- SELECT 'complex_abs_ops', oid FROM pg_type WHERE typname = 'complex_abs';
+ SELECT 'complex_abs_ops', oid FROM pg_type WHERE typname = 'complex';
SELECT oid, opcname, opcdeftype
FROM pg_opclass
WHERE opcname = 'complex_abs_ops';
- +------+-----------------+------------+
- |oid | opcname | opcdeftype |
- +------+-----------------+------------+
- |17314 | complex_abs_ops | 29058 |
- +------+-----------------+------------+
+ oid | opcname | opcdeftype
+--------+-----------------+------------
+ 277975 | complex_abs_ops | 277946
+(1 row)
Note that the oid for your pg_opclass instance will
@@ -257,11 +257,23 @@ SELECT oid, opcname, opcdeftype
from the system later just like we got the oid of the type here.
+
+ The above example assumes that you want to make this new opclass the
+ default index opclass for the complex datatype.
+ If you don't, just insert zero into opcdeftype,
+ rather than inserting the datatype's oid:
+
+
+INSERT INTO pg_opclass (opcname, opcdeftype) VALUES ('complex_abs_ops', 0);
+
+
+
+
So now we have an access method and an operator class.
- We still need a set of operators; the procedure for
+ We still need a set of operators. The procedure for
defining operators was discussed earlier in this manual.
- For the complex_abs_ops operator class on Btrees,
+ For the complex_abs_ops operator class on Btrees,
the operators we require are:
@@ -280,7 +292,7 @@ SELECT oid, opcname, opcdeftype
- Part of the code look like this: (note that we will only show the
+ Part of the C code looks like this: (note that we will only show the
equality operator for the rest of the examples. The other four
operators are very similar. Refer to complex.c
or complex.source for the details.)
@@ -298,30 +310,50 @@ SELECT oid, opcname, opcdeftype
- There are a couple of important things that are happening below.
+ We make the function known to Postgres like this:
+
+CREATE FUNCTION complex_abs_eq(complex, complex)
+ RETURNS bool
+ AS 'PGROOT/tutorial/obj/complex.so'
+ LANGUAGE 'c';
+
- First, note that operators for less-than, less-than-or equal, equal,
- greater-than-or-equal, and greater-than for int4
- are being defined. All of these operators are already defined for
- int4 under the names <, <=, =, >=,
- and >. The new operators behave differently, of course. In order
- to guarantee that Postgres uses these
- new operators rather than the old ones, they need to be named differently
- from the old ones. This is a key point: you can overload operators in
- Postgres, but only if the operator isn't
- already defined for the argument types. That is, if you have <
- defined for (int4, int4), you can't define it again.
- Postgres does not check this when you define
- your operator, so be careful. To avoid this problem, odd names will be
- used for the operators. If you get this wrong, the access methods
- are likely to crash when you try to do scans.
+ There are some important things that are happening here.
- The other important point is that all the operator functions return
- Boolean values. The access methods rely on this fact. (On the other
+ First, note that operators for less-than, less-than-or-equal, equal,
+ greater-than-or-equal, and greater-than for complex
+ are being defined. We can only have one operator named, say, = and
+ taking type complex for both operands. In this case
+ we don't have any other operator = for complex,
+ but if we were building a practical datatype we'd probably want = to
+ be the ordinary equality operation for complex numbers. In that case,
+ we'd need to use some other operator name for complex_abs_eq.
+
+
+
+ Second, although Postgres can cope with operators having
+ the same name as long as they have different input datatypes, C can only
+ cope with one global routine having a given name, period. So we shouldn't
+ name the C function something simple like abs_eq.
+ Usually it's a good practice to include the datatype name in the C
+ function name, so as not to conflict with functions for other datatypes.
+
+
+
+ Third, we could have made the Postgres name of the function
+ abs_eq, relying on Postgres to distinguish it
+ by input datatypes from any other Postgres function of the same name.
+ To keep the example simple, we make the function have the same names
+ at the C level and Postgres level.
+
+
+
+ Finally, note that these operator functions return Boolean values.
+ The access methods rely on this fact. (On the other
hand, the support function returns whatever the particular access method
expects -- in this case, a signed integer.) The final routine in the
file is the "support routine" mentioned when we discussed the amsupport
@@ -330,96 +362,31 @@ SELECT oid, opcname, opcdeftype
-
-CREATE FUNCTION complex_abs_eq(complex_abs, complex_abs)
- RETURNS bool
- AS 'PGROOT/tutorial/obj/complex.so'
- LANGUAGE 'c';
-
-
-
-
- Now define the operators that use them. As noted, the operator names
- must be unique among all operators that take two int4
- operands. In order to see if the operator names listed below are taken,
- we can do a query on pg_operator:
-
-
- /*
- * this query uses the regular expression operator (~)
- * to find three-character operator names that end in
- * the character &
- */
- SELECT *
- FROM pg_operator
- WHERE oprname ~ '^..&$'::text;
-
-
-
-
-
- to see if your name is taken for the types you want. The important
- things here are the procedure (which are the C
- functions defined above) and the restriction and join selectivity
- functions. You should just use the ones used below--note that there
- are different such functions for the less-than, equal, and greater-than
- cases. These must be supplied, or the access method will crash when it
- tries to use the operator. You should copy the names for restrict and
- join, but use the procedure names you defined in the last step.
+ Now we are ready to define the operators:
CREATE OPERATOR = (
- leftarg = complex_abs, rightarg = complex_abs,
+ leftarg = complex, rightarg = complex,
procedure = complex_abs_eq,
restrict = eqsel, join = eqjoinsel
)
+
+ The important
+ things here are the procedure names (which are the C
+ functions defined above) and the restriction and join selectivity
+ functions. You should just use the selectivity functions used in
+ the example (see complex.source).
+ Note that there
+ are different such functions for the less-than, equal, and greater-than
+ cases. These must be supplied, or the optimizer will be unable to
+ make effective use of the index.
- Notice that five operators corresponding to less, less equal, equal,
- greater, and greater equal are defined.
-
-
-
- We're just about finished. the last thing we need to do is to update
- the pg_amop relation. To do this, we need the
- following attributes:
-
-
- pg_amproc Schema
- pg_amproc
-
-
-
- Attribute
- Description
-
-
-
-
- amopid
- the oid of the pg_am instance
- for B-tree (== 403, see above)
-
-
- amopclaid
- the oid of the
- pg_opclass instance for complex_abs_ops
- (== whatever you got instead of 17314, see above)
-
-
- amopopr
- the oids of the operators for the opclass
- (which we'll get in just a minute)
-
-
-
-
-
-
-
- So we need the oids of the operators we just
+ 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 complexes, and pick ours out:
@@ -428,26 +395,22 @@ CREATE OPERATOR = (
INTO 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_abs';
+ and t.typname = 'complex';
- +------+---------+
- |oid | oprname |
- +------+---------+
- |17321 | < |
- +------+---------+
- |17322 | <= |
- +------+---------+
- |17323 | = |
- +------+---------+
- |17324 | >= |
- +------+---------+
- |17325 | > |
- +------+---------+
+ 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 17321 through 17325. The values you
+ 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.
@@ -455,13 +418,13 @@ CREATE OPERATOR = (
Now we're ready to update pg_amop with our new
operator class. The most important thing in this entire discussion
- is that the operators are ordered, from less equal through greater
- equal, in pg_amop. We add the instances we need:
+ is that the operators are ordered, from less than through greater
+ than, in pg_amop. We add the instances we need:
INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
SELECT am.oid, opcl.oid, c.opoid, 1
- FROM pg_am am, pg_opclass opcl, complex_abs_ops_tmp c
+ FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
WHERE amname = 'btree' AND
opcname = 'complex_abs_ops' AND
c.oprname = '<';
@@ -493,15 +456,13 @@ CREATE OPERATOR = (
SELECT oid, proname FROM pg_proc
WHERE proname = 'complex_abs_cmp';
- +------+-----------------+
- |oid | proname |
- +------+-----------------+
- |17328 | complex_abs_cmp |
- +------+-----------------+
+ oid | proname
+--------+-----------------
+ 277997 | complex_abs_cmp
+(1 row)
- (Again, your oid number will probably be different
- and you should substitute the value you see for the value below.)
+ (Again, your oid number will probably be different.)
We can add the new instance as follows:
@@ -515,76 +476,8 @@ CREATE OPERATOR = (
- Now we need to add a hashing strategy to allow the type to be indexed.
- We do this by using another type in pg_am but we reuse the same ops.
-
-
- INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
- SELECT am.oid, opcl.oid, c.opoid, 1
- FROM pg_am am, pg_opclass opcl, complex_abs_ops_tmp c
- WHERE amname = 'hash' AND
- opcname = 'complex_abs_ops' AND
- c.oprname = '=';
-
-
-
-
- In order to use this index in a where clause, we need to modify the
- pg_operator class as follows.
-
-
- UPDATE pg_operator
- SET oprrest = 'eqsel'::regproc, oprjoin = 'eqjoinsel'
- WHERE oprname = '=' AND
- oprleft = oprright AND
- oprleft = (SELECT oid FROM pg_type WHERE typname = 'complex_abs');
-
- UPDATE pg_operator
- SET oprrest = 'neqsel'::regproc, oprjoin = 'neqjoinsel'
- WHERE oprname = '' AND
- oprleft = oprright AND
- oprleft = (SELECT oid FROM pg_type WHERE typname = 'complex_abs');
-
- UPDATE pg_operator
- SET oprrest = 'neqsel'::regproc, oprjoin = 'neqjoinsel'
- WHERE oprname = '' AND
- oprleft = oprright AND
- oprleft = (SELECT oid FROM pg_type WHERE typname = 'complex_abs');
-
- UPDATE pg_operator
- SET oprrest = 'scalarltsel'::regproc, oprjoin = 'scalarltjoinsel'
- WHERE oprname = '<' AND
- oprleft = oprright AND
- oprleft = (SELECT oid FROM pg_type WHERE typname = 'complex_abs');
-
- UPDATE pg_operator
- SET oprrest = 'scalarltsel'::regproc, oprjoin = 'scalarltjoinsel'
- WHERE oprname = '<=' AND
- oprleft = oprright AND
- oprleft = (SELECT oid FROM pg_type WHERE typname = 'complex_abs');
-
- UPDATE pg_operator
- SET oprrest = 'scalargtsel'::regproc, oprjoin = 'scalargtjoinsel'
- WHERE oprname = '>' AND
- oprleft = oprright AND
- oprleft = (SELECT oid FROM pg_type WHERE typname = 'complex_abs');
-
- UPDATE pg_operator
- SET oprrest = 'scalargtsel'::regproc, oprjoin = 'scalargtjoinsel'
- WHERE oprname = '>=' AND
- oprleft = oprright AND
- oprleft = (SELECT oid FROM pg_type WHERE typname = 'complex_abs');
-
-
-
-
- And last (Finally!) we register a description of this type.
-
-
- INSERT INTO pg_description (objoid, description)
- SELECT oid, 'Two part G/L account'
- FROM pg_type WHERE typname = 'complex_abs';
-
+ And we're done! (Whew.) It should now be possible to create
+ and use btree indexes on complex columns.