-<Chapter Id="xoper">
-<Title>Extending <Acronym>SQL</Acronym>: Operators</Title>
-
-<Para>
- <ProductName>Postgres</ProductName> supports left unary, right unary and binary
- operators. Operators can be overloaded, or re-used
- with different numbers and types of arguments. If
- there is an ambiguous situation and the system cannot
- determine the correct operator to use, it will return
- an error and you may have to typecast the left and/or
- right operands to help it understand which operator you
- meant to use.
- To create an operator for adding two complex numbers
- can be done as follows. First we need to create a
- function to add the new types. Then, we can create the
- operator with the function.
-
-<ProgramListing>
- CREATE FUNCTION complex_add(complex, complex)
- RETURNS complex
- AS '$PWD/obj/complex.so'
- LANGUAGE 'c';
-
- CREATE OPERATOR + (
- leftarg = complex,
- rightarg = complex,
- procedure = complex_add,
- commutator = +
- );
-</ProgramListing>
-</Para>
-
-<Para>
- We've shown how to create a binary operator here. To
- create unary operators, just omit one of leftarg (for
- left unary) or rightarg (for right unary).
- If we give the system enough type information, it can
- automatically figure out which operators to use.
+ <Chapter Id="xoper">
+ <Title>Extending <Acronym>SQL</Acronym>: Operators</Title>
+
+ <Para>
+ <ProductName>Postgres</ProductName> supports left unary,
+ right unary and binary
+ operators. Operators can be overloaded, or re-used
+ with different numbers and types of arguments. If
+ there is an ambiguous situation and the system cannot
+ determine the correct operator to use, it will return
+ an error and you may have to typecast the left and/or
+ right operands to help it understand which operator you
+ meant to use.
+ To create an operator for adding two complex numbers
+ can be done as follows. First we need to create a
+ function to add the new types. Then, we can create the
+ operator with the function.
+
+ <ProgramListing>
+CREATE FUNCTION complex_add(complex, complex)
+ RETURNS complex
+ AS '$PWD/obj/complex.so'
+ LANGUAGE 'c';
+
+CREATE OPERATOR + (
+ leftarg = complex,
+ rightarg = complex,
+ procedure = complex_add,
+ commutator = +
+);
+ </ProgramListing>
+ </Para>
+
+ <Para>
+ We've shown how to create a binary operator here. To
+ create unary operators, just omit one of leftarg (for
+ left unary) or rightarg (for right unary).
+ If we give the system enough type information, it can
+ automatically figure out which operators to use.
-<ProgramListing>
- SELECT (a + b) AS c FROM test_complex;
-
- +----------------+
- |c |
- +----------------+
- |(5.2,6.05) |
- +----------------+
- |(133.42,144.95) |
- +----------------+
-</ProgramListing>
-</Para>
-</Chapter>
+ <ProgramListing>
+SELECT (a + b) AS c FROM test_complex;
+
++----------------+
+|c |
++----------------+
+|(5.2,6.05) |
++----------------+
+|(133.42,144.95) |
++----------------+
+ </ProgramListing>
+ </Para>
+
+ <sect1>
+ <title>Hash Join Operators</title>
+
+ <note>
+ <title>Author</title>
+ <para>
+ Written by Tom Lane.
+ </para>
+ </note>
+
+ <para>
+ The assumption underlying hash join is that two values that will be
+ considered equal by the comparison operator will always have the same
+ hash value. If two values get put in different hash buckets, the join
+ will never compare them at all, so they are necessarily treated as
+ unequal.
+ </para>
+
+ <para>
+ But we have a number of datatypes for which the "=" operator is not
+ a straight bitwise comparison. For example, intervaleq is not bitwise
+ at all; it considers two time intervals equal if they have the same
+ duration, whether or not their endpoints are identical. What this means
+ is that a join using "=" between interval fields will yield different
+ results if implemented as a hash join than if implemented another way,
+ because a large fraction of the pairs that should match will hash to
+ different values and will never be compared.
+ </para>
+
+ <para>
+ I believe the same problem exists for float data; for example, on
+ IEEE-compliant machines, minus zero and plus zero have different bit
+ patterns (hence different hash values) but should be considered equal.
+ A hashjoin will get it wrong.
+ </para>
+
+ <para>
+ I will go through pg_operator and remove the hashable flag from
+ operators that are not safely hashable, but I see no way to
+ automatically check for this sort of mistake. The only long-term
+ answer is to raise the consciousness of datatype creators about what
+ it means to set the oprcanhash flag. Don't do it unless your equality
+ operator can be implemented as memcmp()!
+ </para>
+ </sect1>
+ </Chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"./reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
+sgml-local-ecat-files:nil
+End:
+-->