1
1
<!--
2
- $Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.32 2003/08/31 17:32:21 petere Exp $
2
+ $Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.33 2003/10/21 23:28:42 tgl Exp $
3
3
-->
4
4
5
5
<sect1 id="xindex">
@@ -408,7 +408,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.32 2003/08/31 17:32:21 pete
408
408
409
409
<para>
410
410
Now that we have seen the ideas, here is the promised example of
411
- creating a new operator class. The operator class encapsulates
411
+ creating a new operator class.
412
+ (You can find a working copy of this example in
413
+ <filename>src/tutorial/complex.c</filename> and
414
+ <filename>src/tutorial/complex.sql</filename> in the source
415
+ distribution.)
416
+ The operator class encapsulates
412
417
operators that sort complex numbers in absolute value order, so we
413
418
choose the name <literal>complex_abs_ops</literal>. First, we need
414
419
a set of operators. The procedure for defining operators was
@@ -425,40 +430,65 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.32 2003/08/31 17:32:21 pete
425
430
</para>
426
431
427
432
<para>
428
- The C code for the equality operator look like this:
433
+ The least error-prone way to define a related set of comparison operators
434
+ is to write the btree comparison support function first, and then write the
435
+ other functions as one-line wrappers around the support function. This
436
+ reduces the odds of getting inconsistent results for corner cases.
437
+ Following this approach, we first write
429
438
430
439
<programlisting>
431
- #define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
440
+ #define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
432
441
433
- bool
434
- complex_abs_eq (Complex *a, Complex *b)
442
+ static int
443
+ complex_abs_cmp_internal (Complex *a, Complex *b)
435
444
{
436
- double amag = Mag(a), bmag = Mag(b);
437
- return (amag == bmag);
445
+ double amag = Mag(a),
446
+ bmag = Mag(b);
447
+
448
+ if (amag < bmag)
449
+ return -1;
450
+ if (amag > bmag)
451
+ return 1;
452
+ return 0;
438
453
}
439
454
</programlisting>
440
- The other four operators are very similar. You can find their code
441
- in <filename>src/tutorial/complex.c</filename> and
442
- <filename>src/tutorial/complex.sql</filename> in the source
443
- distribution.
455
+
456
+ Now the less-than function looks like
457
+
458
+ <programlisting>
459
+ PG_FUNCTION_INFO_V1(complex_abs_lt);
460
+
461
+ Datum
462
+ complex_abs_lt(PG_FUNCTION_ARGS)
463
+ {
464
+ Complex *a = (Complex *) PG_GETARG_POINTER(0);
465
+ Complex *b = (Complex *) PG_GETARG_POINTER(1);
466
+
467
+ PG_RETURN_BOOL(complex_abs_cmp_internal(a, b) < 0);
468
+ }
469
+ </programlisting>
470
+
471
+ The other four functions differ only in how they compare the internal
472
+ function's result to zero.
444
473
</para>
445
474
446
475
<para>
447
- Now declare the functions and the operators based on the functions:
476
+ Next we declare the functions and the operators based on the functions
477
+ to SQL:
478
+
448
479
<programlisting>
449
- CREATE FUNCTION complex_abs_eq(complex, complex) RETURNS boolean
450
- AS '<replaceable>filename</replaceable>', 'complex_abs_eq'
451
- LANGUAGE C;
452
-
453
- CREATE OPERATOR = (
454
- leftarg = complex,
455
- rightarg = complex,
456
- procedure = complex_abs_eq,
457
- restrict = eqsel,
458
- join = eqjoinsel
480
+ CREATE FUNCTION complex_abs_lt(complex, complex) RETURNS bool
481
+ AS '<replaceable>filename</replaceable>', 'complex_abs_lt'
482
+ LANGUAGE C IMMUTABLE STRICT;
483
+
484
+ CREATE OPERATOR < (
485
+ leftarg = complex, rightarg = complex, procedure = complex_abs_lt,
486
+ commutator = > , negator = >= ,
487
+ restrict = scalarltsel, join = scalarltjoinsel
459
488
);
460
489
</programlisting>
461
- It is important to specify the restriction and join selectivity
490
+ It is important to specify the correct commutator and negator operators,
491
+ as well as suitable restriction and join selectivity
462
492
functions, otherwise the optimizer will be unable to make effective
463
493
use of the index. Note that the less-than, equal, and
464
494
greater-than cases should use different selectivity functions.
@@ -518,7 +548,7 @@ CREATE OPERATOR = (
518
548
CREATE FUNCTION complex_abs_cmp(complex, complex)
519
549
RETURNS integer
520
550
AS '<replaceable>filename</replaceable>'
521
- LANGUAGE C;
551
+ LANGUAGE C IMMUTABLE STRICT ;
522
552
</programlisting>
523
553
</para>
524
554
0 commit comments