<!--
$Header: /usr/prj/pg/cvsroot/doc/doc/src/sgml/xoper.sgml,v 1.5 2001/09/17 01:55:38 i-kaori Exp $
-->

 <Chapter Id="xoper">
  <!--<Title>Extending <Acronym>SQL</Acronym>: Operators</Title>-->
  <Title><Acronym>SQL</Acronym>の拡張――演算子</Title>
<indexterm><primary>SQL</primary><secondary sortas="かくちょう">拡張</secondary><tertiary sortas="えんざんし">演算子</tertiary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="かくちょう">拡張</secondary></indexterm>
  <para>
   <!--<ProductName>Postgres</ProductName> supports left unary,
   right  unary  and  binary
   operators.   Operators  can  be  overloaded; that is,
   the same operator name can be used for different operators
   that have 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.  You may have to typecast the left and/or
   right operands to help it understand which operator you
   meant to use.-->

   <ProductName>Postgres</ProductName>では左単項演算子、右単項演算子、二項演算子をサポートしています。演算子はオーバーロード可能です。つまり、同じ演算子名を引数の数と型が異なる演算子に対して使用する事ができるということです。もし使用する演算子に曖昧な状態があり、システムが使用するべき正しい演算子を決定することができない場合は、エラーを返します。その場合、どの演算子を使いたいのかを明示的に指定するために、左/右演算項目を型キャストする必要があるかもしれません。<indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="ひだりたんこうえんざんし">左単項演算子</secondary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="みぎたんこうえんざんし">右単項演算子</secondary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="にこうえんざんし">二項演算子</secondary></indexterm>
  </para>

  <para>
   <!--Every operator is "syntactic sugar" for a call to an
   underlying function that does the real work; so you must
   first create the underlying function before you can create
   the operator.  However, an operator is <emphasis>not</emphasis>
   merely syntactic sugar, because it carries additional information
   that helps the query planner optimize queries that use the
   operator.  Much of this chapter will be devoted to explaining
   that additional information.-->

   すべての演算子は、実際の処理を行う関数を呼び出す「文法的代理」です。したがって、演算子を作成する前に、まずはその基礎となる関数を作成する必要があります。しかし、演算子は単なる文法的代理だけではありません。その演算子を使う問い合わせを最適化するクエリプランナを補助するための、追加的な情報を伝える機能を持っています。この章の大部分は、この追加的な情報について説明します。
  </para>

  <para>
   <!--Here is an example of creating an operator for adding two
   complex numbers.  We assume we've already created the definition
   of type complex.  First we need a function that does the work;
   then we can define the operator:-->

   ここで2つの複素数を加算する演算子を作成するという例を示します。すでに複素数型を定義しているものとします。まず加算を行う関数を作成する必要があります。その後に演算子を定義できます。
</para>

<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>
   <!--Now we can do:-->
   これで以下の事を実行できるようになります。 
</para>

<programlisting>
SELECT (a + b) AS c FROM test_complex;

+----------------+
|c               |
+----------------+
|(5.2,6.05)      |
+----------------+
|(133.42,144.95) |
+----------------+
</programlisting>

  <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).  The procedure
   clause and the argument clauses are the only required items
   in CREATE OPERATOR.  The COMMUTATOR clause shown in the example
   is an optional hint to the query optimizer.  Further details about
   COMMUTATOR and other optimizer hints appear below.-->

   ここでは二項演算子をどのように作成するのかを示しました。単項演算子を作成するには、単に、左方単項の場合はleftargを、右方単項の場合はrightargを省略するだけです。procedure句とargument句の2つのみがCREATE OPERATORでの必須項目です。例で示したCOMMUTATOR句はオプションで、クエリオプティマイザへのヒントとなります。COMMUTATORとその他のオプティマイザへのヒントについての詳細は後述します。
  </para>

  <sect1 id="xoper-optimization">
   <!--<title>Operator Optimization Information</title>-->
   <title>演算子の最適化に関する情報</title>
<indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="さいてきか">最適化</secondary></indexterm>
   <note>
    <title><!--Author-->著者</title>
    <para>
     <!--Written by-->Tom Lane
    </para>
   </note>

   <para>
    <!--A <ProductName>Postgres</ProductName> operator definition can include
    several optional clauses that tell the system useful things about how
    the operator behaves.  These clauses should be provided whenever
    appropriate, because they can make for considerable speedups in execution
    of queries that use the operator.  But if you provide them, you must be
    sure that they are right!  Incorrect use of an optimization clause can
    result in backend crashes, subtly wrong output, or other Bad Things.
    You can always leave out an optimization clause if you are not sure
    about it; the only consequence is that queries might run slower than
    they need to.-->

    <ProductName>Postgres</ProductName>の演算子定義には、システムに演算子がどう振る舞うかに関する有効な事を伝える、幾つかのオプション句を持つ事ができます。これらの句はその演算子を使用する問い合わせ実行の際に、これらの句の情報により、かなりの速度向上がなされるので、適当なときには常に適応できる状態にしておかなければいけません。しかし、適応する際、それらが正しい事を確認しなければいけません。最適化用の句を間違って使用すると、バックエンドのクラッシュ、不思議な間違った出力、その他有害な事が起こります。最適化用の句についてわからなければ、使用しなくてもかまいません。使用されたときよりも問い合わせの実行が遅くなるかもしれないというだけです。
   </para>

   <para>
    <!--Additional optimization clauses might be added in future versions of
    <ProductName>Postgres</ProductName>.  The ones described here are all
    the ones that release 6.5 understands.-->

    最適化用の句は、<ProductName>Postgres</ProductName>の今後のバージョンでさらに追加される可能性があります。ここで記述したものはすべて、バージョン6.5で有効なものです。
   </para>

   <sect2>
    <title><!--COMMUTATOR-->COMMUTATOR句</title>
<indexterm><primary>COMMUTATOR</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary>COMMUTATOR</secondary></indexterm>
    <para>
     <!--The COMMUTATOR clause, if provided, names an operator that is the
     commutator of the operator being defined.  We say that operator A is the
     commutator of operator B if (x A y) equals (y B x) for all possible input
     values x,y.  Notice that B is also the commutator of A.  For example,
     operators '<' and '>' for a particular datatype are usually each others'
     commutators, and operator '+' is usually commutative with itself.
     But operator '-' is usually not commutative with anything.-->

     COMMUTATOR句が与えられた場合、それはある演算子に定義された演算子の交代演算子であると名付けます。取り得るすべての入力x、yに対して、(x A y)が(y B x)と等しいとき、演算子Aは演算子Bの交代演算子であるといいます。また、BはAの交代演算子となることにも注意してください。たとえば、特定の型用の演算子「&lt;」と「&gt;」は通常、互いの交代演算子になります。演算子「+」は通常自身が交代演算子となります。しかし、演算子「-」は通常交代演算子を持ちません。<indexterm><primary sortas="こうたいえんざんし">交代演算子</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="こうたいえんざんし">交代演算子</secondary></indexterm>
    </para>

    <para>
     <!--The left argument type of a commuted operator is the same as the
     right argument type of its commutator, and vice versa.  So the name of
     the commutator operator is all that <ProductName>Postgres</ProductName>
     needs to be given to look up the commutator, and that's all that need
     be provided in the COMMUTATOR clause.-->

     交代された演算子の左引数の型は、その交代演算子の右引数の型と同一で、その逆も又同様です。したがって、<ProductName>Postgres</ProductName>で演算子を検索するときに必要なものは交代演算子の名前のみであり、COMMUTATOR句ではそれのみが与えられていればよいです。
    </para>

    <para>
     <!--When you are defining a self-commutative operator, you just do it.
     When you are defining a pair of commutative operators, things are
     a little trickier: how can the first one to be defined refer to the
     other one, which you haven't defined yet?  There are two solutions
     to this problem:-->

     交代演算子である演算子を定義する場合は、単にそれを指定するだけです。交代演算子のペアを定義する場合は少し複雑になります。最初に他の未定義のものを参照するものをどう定義するのかということが問題となります。この問題には下記の2つの解決方法があります。
</para>

     <itemizedlist>
      <listitem>
       <para>
	<!--One way is to omit the COMMUTATOR clause in the first operator that
	you define, and then provide one in the second operator's definition.
	Since <ProductName>Postgres</ProductName> knows that commutative
	operators come in pairs, when it sees the second definition it will
	automatically go back and fill in the missing COMMUTATOR clause in
	the first definition.-->

        1つ目の方法は、最初の演算子を定義する際にCOMMUTATOR句を省略し、2番目の演算子の定義では、COMMUTATOR句に最初の演算子を与えるという方法です。<ProductName>Postgres</ProductName>は交代演算子がペアになっていることがわかっていますので、2番目の定義を見たときに、自動的に最初の定義に戻ってその未定義になっているCOMMUTATOR句を設定します。
       </para>
      </listitem>

      <listitem>
       <para>
	<!--The other, more straightforward way is just to include COMMUTATOR clauses
	in both definitions.  When <ProductName>Postgres</ProductName> processes
	the first definition and realizes that COMMUTATOR refers to a non-existent
	operator, the system will make a dummy entry for that operator in the
	system's pg_operator table.  This dummy entry will have valid data only
	for the operator name, left and right argument types, and result type,
	since that's all that <ProductName>Postgres</ProductName> can deduce
	at this point.  The first operator's catalog entry will link to this
	dummy entry.  Later, when you define the second operator, the system
	updates the dummy entry with the additional information from the second
	definition.  If you try to use the dummy operator before it's been filled
	in, you'll just get an error message.  (Note: this procedure did not work
	reliably in <ProductName>Postgres</ProductName> versions before 6.5,
	but it is now the recommended way to do things.)-->

        もう1つの方法は、両方の定義にCOMMUTATOR句を含めるというもっと素直な方法です。<ProductName>Postgres</ProductName>は最初の定義を処理する際に、COMMUTATORが存在しない演算子を参照している事がわかると、システムはその演算子用の仮のエントリをシステムテーブルのpg_operatorに作成します。この仮エントリには、<ProductName>Postgres</ProductName>がこの時点で推定できる演算子名、左引数の型、右引数の型、結果の型についてのみの有効なデータが入ります。最初の演算子のカタログエントリはこの仮エントリに結び付きます。この後、2番目の演算子が定義されたら、システムはその仮エントリに追加情報を更新します。更新される前に仮演算子を使用すると、エラーメッセージが出力されます（注意：バージョン6.5より前の<ProductName>Postgres</ProductName>ではこの方法は信頼性がありませんでしたが、今ではこの方法が推奨されています）。
       </para>
      </listitem>
     </itemizedlist>
   </sect2>


   <sect2>
    <title><!--NEGATOR-->NEGATOR句</title>
<indexterm><primary>NEGATOR</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary>NEGATOR</secondary></indexterm>
    <para>
     <!--The NEGATOR clause, if provided, names an operator that is the
     negator of the operator being defined.  We say that operator A
     is the negator of operator B if both return boolean results and
     (x A y) equals NOT (x B y) for all possible inputs x,y.
     Notice that B is also the negator of A.
     For example, '<' and '>=' are a negator pair for most datatypes.
     An operator can never be validly be its own negator.-->

     NEGATOR句が定義された場合、それはある演算子に定義された演算子の否定子であるとします。入力値、xとyの取り得るすべての値に対して両方の演算子がブール値を返し、(x A y)がNOT (x B y)と等しい場合、演算子Aは演算子Bの否定子であるといいます。また、BはAの否定子でもあることに注意してください。たとえば、ほとんどの型では「&lt;」と「&gt;=」は否定子のペアとなります。演算子が自身の否定子になることは決してありません。<indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="ひていし">否定子</secondary></indexterm>
    </para>

   <para>
    <!--Unlike COMMUTATOR, a pair of unary operators could validly be marked
    as each others' negators; that would mean (A x) equals NOT (B x)
    for all x, or the equivalent for right-unary operators.-->

    COMMUTATOR句とは異なり、単項演算子のペアは互いの否定子になり得ます。それはつまり、xの取り得るすべての値に対して、(A x)がNOT (B x)に等しいこと、また、右単項演算子の場合も同様の等式がなりたつことを意味します。
   </para>

   <para>
    <!--An operator's negator must have the same left and/or right argument types
    as the operator itself, so just as with COMMUTATOR, only the operator
    name need be given in the NEGATOR clause.-->

    演算子の否定子は、COMMUTATOR句と同様に、その演算子の左引数、右引数の型と同じものをとらなければいけません。演算子の名前のみはNEGATOR句で指定されたものでなければいけません。
   </para>

   <para>
    <!--Providing NEGATOR is very helpful to the query optimizer since
    it allows expressions like NOT (x = y) to be simplified into
    x &lt;&gt; y.  This comes up more often than you might think, because
    NOTs can be inserted as a consequence of other rearrangements.-->

    NOT (x = y)といった式をx &lt;&gt; yといった形に単純化させることが可能なので、NEGATORを与える事は問い合わせオプティマイザにとって非常に役に立ちます。他の再配置の結果としてNOTが挿入されることがありますので、この現象は想像以上に多く起こります。
   </para>

   <para>
    <!--Pairs of negator operators can be defined using the same methods
    explained above for commutator pairs.-->

    否定子のペアは、上記の交代演算子のペアで説明した方法と同じ方法で定義することができます。
   </para>

  </sect2>

  <sect2>
   <title><!--RESTRICT-->RESTRICT句</title>
<indexterm><primary>RESTRICT</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary>RESTRICT</secondary></indexterm>
   <para>
    <!--The RESTRICT clause, if provided, names a restriction selectivity
    estimation function for the operator (note that this is a function
    name, not an operator name).  RESTRICT clauses only make sense for
    binary operators that return boolean.  The idea behind a restriction
    selectivity estimator is to guess what fraction of the rows in a
    table will satisfy a WHERE-clause condition of the form-->

    RESTRICT句が与えられた場合、それは、その演算子用の制限選択評価関数を指定します（演算子名ではなく関数名であることに注意してください）。RESTRICT句はブール値を返す二項演算子に対してのみ有効です。制限選択評価の背景には、指定した演算子と特定の定数に対して、下記のWHERE句の条件を満たすものはテーブルの中でどのくらいの割合の行が存在するかを推測することです。<indexterm><primary sortas="せいげんせんたくひょうかかんすう">制限選択評価関数</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="せんげんせんたくひょうかかんすう">制限選択評価関数</secondary></indexterm>
</para>

<programlisting>
field OP constant
</programlisting>

<para>
    <!--for the current operator and a particular constant value.
    This assists the optimizer by
    giving it some idea of how many rows will be eliminated by WHERE
    clauses that have this form.  (What happens if the constant is on
    the left, you may be wondering?  Well, that's one of the things that
    COMMUTATOR is for...)-->

    この形式を持ったWHERE句を使って、どのくらいの行が除外されるのかを通知することで、オプティマイザの手助けをします（定数値が左項にあったら何が起こるかという疑問が生じるかも知れませんが、それはCOMMUTATORが存在する理由の1つでもあります）。
   </para>

   <para>
    <!--Writing new restriction selectivity estimation functions is far beyond
    the scope of this chapter, but fortunately you can usually just use
    one of the system's standard estimators for many of your own operators.
    These are the standard restriction estimators:-->

    新しい制限選択評価関数の記述方法はこの章の内容を越えていますが、幸いな事に、たいていの場合システムが持つ標準的な評価関数を使って、多くの自作演算子用が作成できます。標準的な制限評価関数には下記のものがあります。
</para>

<programlisting>
eqsel       for =
neqsel      for &lt;&gt;
scalarltsel for &lt; or &lt;=
scalargtsel for &gt; or &gt;=
</programlisting>

<para>
    <!--It might seem a little odd that these are the categories, but they
    make sense if you think about it.  '=' will typically accept only
    a small fraction of the rows in a table; '&lt;&gt;' will typically reject
    only a small fraction.  '&lt;' will accept a fraction that depends on
    where the given constant falls in the range of values for that table
    column (which, it just so happens, is information collected by
    VACUUM ANALYZE and made available to the selectivity estimator).
    '&lt;=' will accept a slightly larger fraction than '&lt;' for the same
    comparison constant, but they're close enough to not be worth
    distinguishing, especially since we're not likely to do better than a
    rough guess anyhow.  Similar remarks apply to '&gt;' and '&gt;='.-->

    これらがカテゴリであることは少し奇妙に思えるかもしれませんが、これらには歴とした意味があります。「=」は一般的にテーブル内の行の小さな部分を受け付けます。「&lt;&gt;」は一般的に小さな部分を除きます。「&lt;」は、指定した定数がテーブルカラム（これはVACUUM ANALYZEによって収集される情報で、選択評価関数で使用できるように作成されます）のとる値の範囲のどの辺りにあるのかに依存する量の部分を受け付けます。「&lt;=」は「&lt;」よりも少しだけ大きな部分を受け付けます。この差は比較に用いた定数と同じ部分のためですが、特に大雑把な推測以上のことを行うのは適切ではありませんので、区別する価値がないといえる位近い値です。「&gt;」と「&gt;=」についても同様のことがいえます。
   </para>

   <para>
    <!--You can frequently get away with using either eqsel or neqsel for
    operators that have very high or very low selectivity, even if they
    aren't really equality or inequality.  For example, the
    approximate-equality geometric operators use eqsel on the assumption that
    they'll usually only match a small fraction of the entries in a table.-->

    非常に高い/低い選択性をもつ演算子に、まったく等しい場合/等しくない場合で、eqselかneqselを使用しないでおく事も可能です。たとえば、ほぼ等しい幾何演算子ではテーブルのエントリの小部分にのみに合うものと仮定してeqselを使用します。</para>

   <para>
    <!--You can use scalarltsel and scalargtsel for comparisons on datatypes that
    have some sensible means of being converted into numeric scalars for
    range comparisons.  If possible, add the datatype to those understood
    by the routine convert_to_scalar() in src/backend/utils/adt/selfuncs.c.
    (Eventually, this routine should be replaced by per-datatype functions
    identified through a column of the pg_type table; but that hasn't happened
    yet.)  If you do not do this, things will still work, but the optimizer's
    estimates won't be as good as they could be.-->

    範囲比較のために数スカラーに変換された際に、敏感になる型を比較するために、scalarltselとscalargtselを使用することも可能です。可能であるならばsrc/backend/utils/adt/selfuncs.cにある、convert_to_scalar()のルーチンで理解できるところに追加してください（今後、このルーチンはpg_typeテーブルの行で指定されたper-datatype関数で置き換えられなければいけませんが、まだ行われていません）。これを行わなくても動きますが、オプティマイザの推測機能はその機能を発揮できません。
   </para>

   <para>
    <!--There are additional selectivity functions designed for geometric
    operators in src/backend/utils/adt/geo_selfuncs.c: areasel, positionsel,
    and contsel.  At this writing these are just stubs, but you may want
    to use them (or even better, improve them) anyway.-->

    幾何演算子に対しての追加選択関数（areasel、positionsel、contsel）はsrc/backend/utils/adt/geo_selfuncs.cに書かれています。このドキュメントを書いている時点では、これらは単なるスタブですが、ともかく使いたい（あるいは改良したい）こともあるでしょう。<indexterm><primary sortas="ついかせんたくかんすう">追加選択関数</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="ついかせんたくかんすう">追加選択関数</secondary></indexterm>
   </para>
   </sect2>

   <sect2>
    <title><!--JOIN-->JOIN句</title>
<indexterm><primary>JOIN</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary>JOIN</secondary></indexterm>
    <para>
     <!--The JOIN clause, if provided, names a join selectivity
     estimation function for the operator (note that this is a function
     name, not an operator name).  JOIN clauses only make sense for
     binary operators that return boolean.  The idea behind a join
     selectivity estimator is to guess what fraction of the rows in a
     pair of tables will satisfy a WHERE-clause condition of the form-->

     JOIN句が与えられた場合、それはその演算子用の結合選択評価関数の名前を示します（これが演算子名ではなく関数名であることに注意してください）。JOIN句はブール値を返す二項演算子のみ有効です。結合選択評価関数の背景には、対象とする現在の演算子で、下記の形式のWHERE句条件を満たす行は2つのテーブルの間でどのくらいの割合で存在するのかを推測する事が挙げられます。<indexterm><primary sortas="けつごうせんたくひょうかかんすう">結合選択評価関数</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="けつごうせんたくひょうかかんすう">結合選択評価関数</secondary></indexterm>
</para>

<programlisting>
table1.field1 OP table2.field2
</programlisting>

<para>
     <!--for the current operator.  As with the RESTRICT clause, this helps
     the optimizer very substantially by letting it figure out which
     of several possible join sequences is likely to take the least work.-->

     RESTRICT句の使用と同様、これは、いくつかの取り得る結合シーケンスのうちどれが最も仕事量が少ないように考えられるのかをオプティマイザに計算させることで大きなオプティマイザへの援助となります。
    </para>

    <para>
     <!--As before, this chapter will make no attempt to explain how to write
     a join selectivity estimator function, but will just suggest that
     you use one of the standard estimators if one is applicable:-->

     前と同様に、この章では結合選択評価関数の書き方を説明しませんが、もし適用できるならば下記の標準的な評価関数のうちの1つを使う事を勧めます。
</para>

<programlisting>
eqjoinsel   for =
neqjoinsel  for &lt;&gt;
scalarltjoinsel for &lt; or &lt;=
scalargtjoinsel for &gt; or &gt;=
areajoinsel for 2D area-based comparisons
positionjoinsel for 2D position-based comparisons
contjoinsel for 2D containment-based comparisons
</programlisting>
   </sect2>

   <sect2>
    <title><!--HASHES-->HASHES句</title>
<indexterm><primary>HASHES</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary>HASHES</secondary></indexterm>
    <para>
     <!--The HASHES clause, if present, tells the system that it is OK to
     use the hash join method for a join based on this operator.  HASHES
     only makes sense for binary operators that return boolean, and
     in practice the operator had better be equality for some data type.-->

     HASHES句が存在する場合、それはシステムに対して、この演算子に基づいた結合にハッシュ結合方法を使っても問題がない事を伝えます。HASHES句はブール値を返す二項演算子にのみ有効です。実際には、あるデータ型の等価性を求める演算子であった方がよいでしょう。<indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="はっしゅけつごう">ハッシュ結合</secondary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="とうかせい">等価性</secondary></indexterm>
    </para>

    <para>
     <!--The assumption underlying hash join is that the join operator can
     only return TRUE for pairs of left and right values that hash to the
     same hash code.  If two values get put in different hash buckets, the
     join will never compare them at all, implicitly assuming that the
     result of the join operator must be FALSE.  So it never makes sense
     to specify HASHES for operators that do not represent equality.-->

     ハッシュ結合の基礎となっている仮定は、結合演算子は左項と右項の値が同じハッシュコードを持つときにのみ真を返すことができるということです。2つの値が異なるハッシュの入れ物に置かれた場合、結合演算子の結果が必ず偽であるという仮定を、結合は暗黙的に行い、それらを比べる事をしません。したがって、等価性を表さない演算子にHASHES句を指定することはまったく意味がありません。
    </para>

    <para>
     <!--In fact, logical equality is not good enough either; the operator
     had better represent pure bitwise equality, because the hash function
     will be computed on the memory representation of the values regardless
     of what the bits mean.  For example, equality of
     time intervals is not bitwise equality; the interval equality operator
     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 would 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 by the hash join.  But
     if the optimizer chose to use a different kind of join, all the pairs
     that the equality operator says are equal will be found.
     We don't want that kind of inconsistency, so we don't mark interval
     equality as hashable.-->

     実際は、論理的な等価性は十分ではなく、演算子は純粋にビット単位の等価性を表すものの方が好ましいです。なぜならば、ハッシュ関数は、ビットの意味は関係なく、メモリ内の値表現を使って計算されるからです。たとえば、時間間隔の等価性はビット単位での等価性ではなく、間隔の等価性演算子は、2つの時間間隔がその終了時刻が異なっていた場合でも、期間が同一であれば、その時間間隔は等価であるとみなします。これは、間隔フィールドとの間で「=」を使った結合は、ハッシュ結合を実装した場合とそれ以外で実装した場合とで、異なる結果をもたらすことを意味しています。それは、合うべきペアの多くの部分は異なる値にハッシュされ、ハッシュ結合時に比較されなくなるために起こります。しかし、オプティマイザが他種類の結合を使用する事を選んだ場合、等価性演算子が同一であるとしたすべてのペアが見つかります。このような矛盾は好ましくありませんので、間隔の等価性をハッシュ可能とはしません。<indexterm><primary sortas="とうかせいえんざんし">等価性演算子</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="とうかせいえんざんし">等価性演算子</secondary></indexterm>
    </para>

    <para>
     <!--There are also machine-dependent ways in which a hash join might fail
     to do the right thing.  For example, if your datatype
     is a structure in which there may be uninteresting pad bits, it's unsafe
     to mark the equality operator HASHES.  (Unless, perhaps, you write
     your other operators to ensure that the unused bits are always zero.)
     Another example is that the FLOAT datatypes are unsafe for hash
     joins.  On machines that meet the IEEE floating point standard, minus
     zero and plus zero are different values (different bit patterns) but
     they are defined to compare equal.  So, if float equality were marked
     HASHES, a minus zero and a plus zero would probably not be matched up
     by a hash join, but they would be matched up by any other join process.-->

     マシンによっては、ハッシュ結合が適切な処理を行わずに失敗することがあります。たとえば、データ型が不要な部分を埋めたビットを持つ可能性がある構造である場合、その等価性演算子にHASHES句を付けることは安全ではありません（他の演算子を不要なビットが常に0になるように作成している場合は状況が変わる場合があります）。この他の例として、FLOATデータ型でハッシュ結合を使用するには安全ではない場合があります。IEEE浮動小数点標準をみたすマシンではマイナス0とプラス0は異なる値（異なるビット列）となりますが、等価であるものと定義されます。したがって、浮動小数点の等価性演算子にHASHES句を付けると、マイナス0とプラス0はハッシュ結合では多分一致されませんが、他の結合処理では一致するものとされます。
    </para>

    <para>
     <!--The bottom line is that you should probably only use HASHES for
     equality operators that are (or could be) implemented by memcmp().-->

     つまり、memcmp()で実装された（できた）等価性演算子にのみにHASHES句を使用するべきです。
    </para>

   </sect2>

   <sect2>
    <!--<title>SORT1 and SORT2</title>-->
    <title>SORT1句とSORT2句</title>
<indexterm><primary>SORT1</primary></indexterm><indexterm><primary>SORT2</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary>SORT2</secondary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary>SORT1</secondary></indexterm><indexterm><primary sortas="ならべかえ">並べ替え</primary></indexterm><indexterm><primary sortas="そーと">ソート</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="そーと">ソート</secondary></indexterm>
    <para>
     <!--The SORT clauses, if present, tell the system that it is permissible to use
     the merge join method for a join based on the current operator.
     Both must be specified if either is.  The current operator must be
     equality for some pair of data types, and the SORT1 and SORT2 clauses
     name the ordering operator ('<' operator) for the left and right-side
     data types respectively.-->

     SORT句がある場合、それはシステムに対して指定演算子に基づいた結合にマージ結合方式を使う事ができることを伝えます。どちらか一方がそうであるならば、両方が指定されなければならなく、指定演算子はあるデータ型のペアの等価性演算子でなければいけません。また、SORT1句とSORT2句はそれぞれ左側、右側用の順序付演算子（「<」演算子）の名前を示します。<indexterm><primary sortas="まーじけつごう">マージ結合</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="まーじけつごう">マージ結合</secondary></indexterm><indexterm><primary sortas="じゅんじょづけえんざんし">順序付演算子</primary></indexterm><indexterm><primary sortas="えんざんし">演算子</primary><secondary sortas="じゅんじょづけえんざんし">順序付演算子</secondary></indexterm>
    </para>

    <para>
     <!--Merge join is based on the idea of sorting the left and righthand tables
     into order and then scanning them in parallel.  So, both data types must
     be capable of being fully ordered, and the join operator must be one
     that can only succeed for pairs of values that fall at the "same place"
     in the sort order.  In practice this means that the join operator must
     behave like equality.  But unlike hashjoin, where the left and right
     data types had better be the same (or at least bitwise equivalent),
     it is possible to mergejoin two
     distinct data types so long as they are logically compatible.  For
     example, the int2-versus-int4 equality operator is mergejoinable.
     We only need sorting operators that will bring both datatypes into a
     logically compatible sequence.-->

     マージ結合は、テーブルの左側、右側を順序よくソートし、並列にスキャンするという考えに基づいています。したがって、両データ型は十分に順序付けされている必要があり、結合演算子はソート順で「同じ場所」にある値のペアをのみを成功したものとするものである必要があります。実際問題として、これは、結合演算子は等価性のような振る舞いをしなければいけないことを意味しています。左右のデータ型が同じ（または少なくともビット単位での等価）であることが望ましいとされるハッシュ結合とは異なり、マージ結合は論理的な互換性を持つ別の2つのデータ型をとることができます。たとえば、int2対int4の等価性演算子はマージ結合が可能です。両方のデータ型を論理的な互換性を保つ順番にソートする演算子のみが必要です。
    </para>

    <para>
     <!--When specifying merge sort operators, the current operator and both
     referenced operators must return boolean; the SORT1 operator must have
     both input datatypes equal to the current operator's left argument type,
     and the SORT2 operator must have
     both input datatypes equal to the current operator's right argument type.
     (As with COMMUTATOR and NEGATOR, this means that the operator name is
     sufficient to specify the operator, and the system is able to make dummy
     operator entries if you happen to define the equality operator before
     the other ones.)-->

     マージソート演算子を指定するときは、対象とする演算子と参照された両演算子はブール値を返さなければいけません。SORT1演算子は、対象とする演算子の左引数の型と同じデータ型を入力として2つ持たなければいけません。SORT2演算子は、対象とする演算子の右引数の型と同じデータ型を入力として2つ持たなければいけません（COMMUTATORとNEGATORを使うときと同じように、演算子名は演算子の指定に十分なものです。他を定義する前に、等価性演算子を定義すると、システムは仮演算子エントリを作成する事ができます）。

    </para>

    <para>
     <!--In practice you should only write SORT clauses for an '=' operator,
     and the two referenced operators should always be named '<'.  Trying
     to use merge join with operators named anything else will result in
     hopeless confusion, for reasons we'll see in a moment.-->

     実際には、「=」演算子用のSORT句だけを記述し、2つの参照される演算子を常に「<」という名前にしておくべきです。他の名前の演算子を使ってマージ結合を使用すると、絶望的な混乱を引き起こします。その理由は後に説明します。

    </para>

    <para>
     <!--There are additional restrictions on operators that you mark
     mergejoinable.  These restrictions are not currently checked by
     CREATE OPERATOR, but a merge join may fail at runtime if any are
     not true:-->

     マージ結合を行う演算子には追加的な制約があります。この制約は今のところCREATE OPERATORで点検されませんが、これが真でなければ、マージ結合は実行時に失敗する可能性があります。
</para>

     <itemizedlist>
      <listitem>
       <para>
	<!--The mergejoinable equality operator must have a commutator
	(itself if the two data types are the same, or a related equality operator
	if they are different).-->

        マージ結合が可能な等価性演算子は交替演算子（2つのデータ型が同じならば、演算子自身、もしくはこれに関連した等価性演算子）を持つ必要があります。
       </para>
      </listitem>

      <listitem>
       <para>
	<!--There must be '<' and '>' ordering operators having the same left and
	right input datatypes as the mergejoinable operator itself.  These
	operators <emphasis>must</emphasis> be named '<' and '>'; you do
	not have any choice in the matter, since there is no provision for
	specifying them explicitly.  Note that if the left and right data types
	are different, neither of these operators is the same as either
	SORT operator.  But they had better order the data values compatibly
	with the SORT operators, or mergejoin will fail to work.-->

        左右とも同じ入力データ型で、かつマージ結合可能な演算子を持つ順序付演算子「&lt;」と「&gt;」が必要です。この演算子は「&lt;」と「&gt;」という名前である必要があり、これらを明示的に指定する方法はないので、この点については選択の余地がありません。左右のデータ型が異なる場合、この演算子は互いのSORT演算子と異なるものであることに注意してください。しかし、SORT演算子を使った場合の順序と互換性を持たせなければ、マージ結合は失敗します。
       </para>
      </listitem>
     </itemizedlist>
   </sect2>

  </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:
-->
