<!--
$Header: /usr/prj/pg/cvsroot/doc/doc/src/sgml/xindex.sgml,v 1.9 2001/08/31 04:18:50 t-ishii Exp $
Postgres documentation
-->

 <chapter id="xindex">
  <!-- <title>Interfacing Extensions To Indices</title>-->
  <title>インデックス拡張機能へのインターフェイス</title>
<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="かくちょう">拡張</secondary></indexterm>
  <para>
   <!-- 
   The procedures described thus far let you define a new type, new
   functions and new operators.  However, we cannot yet define a secondary
   index (such as a <acronym>B-tree</acronym>, <acronym>R-tree</acronym> or
   hash access method) over a new type or its operators. -->

   これまでのところでは、新しい型、新しい関数、新しい演算子をどのように定義するかについて説明してきました。しかしながら、新しい型やその演算子に対する（B-tree、R-tree、ハッシュアクセスメソッドなどを使った）二次インデックスについては説明していませんでした。<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="にじいんでっくす">二次インデックス</secondary></indexterm>

  </para>

  <para>
   <!-- Look back at
   <xref linkend="EXTEND-CATALOGS">.
   The right half shows the  catalogs  that we must modify in order to tell
   <productname>Postgres</productname> how to use a user-defined type and/or
   user-defined  operators with an index (i.e., <filename>pg_am, pg_amop,
    pg_amproc, pg_operator</filename> and <filename>pg_opclass</filename>).
   Unfortunately, there is no simple command to do this.  We will demonstrate
   how to modify these catalogs through a running example:  a  new  operator
   class for the <acronym>B-tree</acronym> access method that stores and
   sorts complex numbers in ascending absolute value order. -->

    <xref linkend="EXTEND-CATALOGS">をもう一度読み返してみてください。この図の右半分では、ユーザー定義の型とインデックス付きのユーザー定義演算子（<filename>pg_am</filename>、<filename>pg_amop</filename>、<filename>pg_amproc</filename>、<filename>pg_operators</filename>、<filename>pg_opclass</filename>）の使い方を<productname>Postgres</productname>に対して伝えるために変更する必要のあるカタログに関して紹介しています。残念ながら、これらのことを簡単に行うコマンドはありません。ここでは、これらのカタログを変更する方法を複素数を値の絶対値の昇順にソートする、<acronym>B-tree</acronym>アクセスメソッドを使った新しい演算子クラスを作るという例を通して紹介します。

  </para>

  <para>
   <!--
   The <filename>pg_am</filename> table contains one row for every user
   defined access method.  Support for the heap access method is built into
   <productname>Postgres</productname>, but every other access method is
   described here.  The schema is -->

   <filename>pg_am</filename>テーブルにはユーザー定義の各アクセスメソッド用の行が1つずつ含まれています。<productname>Postgres</productname>にはヒープアクセスメソッドが組み込まれていますが、他のすべてのアクセスメソッドはこのテーブルで記述されています。スキーマは以下のとおりです。
</para>

   <table tocentry="1">
    <!-- <title>Index Schema</title> -->
    <title>インデックスのスキーマ</title>
    <titleabbrev>Indices</titleabbrev>
<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="すきーま">スキーマ</secondary></indexterm>
    <tgroup cols="2">
     <thead>
      <row>
       <!-- <entry>Column</entry> 
       <entry>Description</entry> -->
       <entry>列</entry> 
       <entry>説明</entry>
      </row>
     </thead>
     <tbody>
      <row>
       <entry>amname<indexterm><primary>amname</primary></indexterm><indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="すきーま">スキーマ</secondary><tertiary>amname</tertiary></indexterm></entry>
       <!-- <entry>name of the access method</entry> -->
       <entry>アクセスメソッド名</entry>
      </row>
      <row>
       <entry>amowner<indexterm><primary>amowner</primary></indexterm><indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="すきーま">スキーマ</secondary><tertiary>amowner</tertiary></indexterm></entry>
       <!-- <entry>user id of the owner</entry> -->
       <entry>所有者のユーザーID</entry> 
      </row>
      <row>
       <entry>amstrategies<indexterm><primary>amstrategies</primary></indexterm><indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="すきーま">スキーマ</secondary><tertiary>amstrategies</tertiary></indexterm></entry>
   <!--<entry>number of strategies for this access method (see below)</entry>
       -->
       <entry>このアクセスメソッド用のストラテジの数（後述）</entry> 
      </row>
      <row>
       <entry>amsupport<indexterm><primary>amsupport</primary></indexterm><indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="すきーま">スキーマ</secondary><tertiary>amsupport</tertiary></indexterm></entry>
  <!-- <entry>number of support routines for this access method (see below)</entry> -->
       <entry>このアクセスメソッド用のサポートルーチンの数（後述）</entry>
      </row>
      <row>
       <entry>amorderstrategy<indexterm><primary>amorderstrategy</primary></indexterm><indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="すきーま">スキーマ</secondary><tertiary>amorderstrategy</tertiary></indexterm></entry>
  <!-- <entry>zero if the index offers no sort order, otherwise the strategy
        number of the strategy operator that describes the sort order</entry>
     -->
       <entry>インデックスがソート順を提供しない場合は0、その他の場合はソート順を説明するストラテジ演算子のストラテジ数</entry>
      </row>
      <row>
       <entry>amgettuple<indexterm><primary>amgettuple</primary></indexterm><indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="すきーま">スキーマ</secondary><tertiary>amgettuple</tertiary></indexterm></entry>
      </row>
      <row>
       <entry>aminsert<indexterm><primary>aminsert</primary></indexterm><indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="すきーま">スキーマ</secondary><tertiary>aminsert</tertiary></indexterm></entry>
      </row>
      <row>
       <entry>...</entry>
       <!--  
       <entry>procedure  identifiers  for  interface routines to the access
	method.  For example, regproc ids for opening,  closing,  and
	getting rows from the access method appear here.</entry> -->
       <entry>アクセスメソッドへのインターフェイスルーチン用のプロシージャ識別子。たとえばregproc idは、ここで紹介するアクセスメソッドをオープン/クローズしたり、そこからインスタンスを取得したりするためのものです。
       </entry>
      </row>
     </tbody>
    </tgroup>
   </table>

  <para>
   <!-- The <acronym>object ID</acronym> of the row in
   <filename>pg_am</filename> is used as a foreign key in a lot of other
   tables.  You  do not  need to  add a new rows to this table; all that
   you are interested in is the <acronym>object ID</acronym> of the access
   method row you want to extend: -->

   <filename>pg_am</filename>の中の行の<acronym>オブジェクトID</acronym>は他のたくさんのテーブルの中で外部キーとして使われています。このテーブルには新しい行を追加する必要はありません。唯一重要なのは拡張したい行のアクセスメソッドの<acronym>オブジェクトID</acronym>です。
</para>

<programlisting>
SELECT oid FROM pg_am WHERE amname = 'btree';

 oid
-----
 403
(1 row)
</programlisting>

<para>
   <!-- 
   We will use that <command>SELECT</command> in a <command>WHERE</command>
   clause later. -->
   後の<command>WHERE</command>節内にてこの<command>SELECT</command>を使います。 

  </para>

  <para>
   <!-- 
   The <filename>amstrategies</filename> column exists to standardize
   comparisons across data types.  For example, <acronym>B-tree</acronym>s
   impose a strict ordering on keys, lesser to greater.  Since
   <productname>Postgres</productname> allows the user to define operators,
   <productname>Postgres</productname> cannot look at the name of an operator
   (e.g., "&gt;" or "&lt;") and tell what kind of comparison it is.  In fact,
   some  access methods don't impose any ordering at all.  For example,
   <acronym>R-tree</acronym>s express a rectangle-containment relationship,
   whereas a hashed data structure expresses only bitwise similarity based
   on the value of a hash function.  <productname>Postgres</productname>
   needs some consistent way of taking a qualification in your query,
   looking at the operator and then deciding if a usable index exists.  This
   implies that <productname>Postgres</productname> needs to know, for
   example, that the  "&lt;="  and  "&gt;" operators partition a
   <acronym>B-tree</acronym>.  <productname>Postgres</productname>
   uses strategies to express these relationships  between
   operators and the way they can be used to scan indices. -->

   <filename>amstrategies</filename>列は、データ型をまたがる比較処理を標準化するためのものです。たとえば<acronym>B-tree</acronym>の場合、キーが小さい方から大きい方へ厳密に並んでいなければいけません。<productname>Postgres</productname>ではユーザーが演算子を定義できますので、<productname>Postgres</productname>は演算子（たとえば「&gt;」や「&lt;」）の名前を見ても、その演算子がどのような比較を行うのかはわかりません。実際、アクセスメソッドによってはまったく順序性を規定しないものもあります。たとえば<acronym>R-tree</acronym>は四角形に閉じた関係を表しますが、そのハッシュデータの構造はハッシュ関数の値によってビットごとの類似性を表しているだけです。<productname>Postgres</productname>は、ある一貫性を持った方法で、クエリ内の条件を取り出し、演算子を探し、インデックスが使用可能かどうかを決定する必要があります。ということは、<productname>Postgres</productname>は、たとえば「&lt;=」や「&gt;」演算子は<acronym>B-tree</acronym>を区切るということを知っている必要があることになります。<productname>Postgres</productname>はストラテジを用いて、演算子とインデックスをスキャンする方法との間のこれらの関係を表現しています。<indexterm><primary>B-tree</primary></indexterm><indexterm><primary>R-tree</primary></indexterm><indexterm><primary sortas="いんでっくす">インデックス</primary><secondary>B-tree</secondary></indexterm><indexterm><primary sortas="いんでっくす">インデックス</primary><secondary>R-tree</secondary></indexterm>
  </para>

  <para><!-- 
   Defining a new set of strategies is beyond the scope of this discussion,
   but we'll explain how <acronym>B-tree</acronym> strategies work because
   you'll need to know that to add a new operator class. In the
   <filename>pg_am</filename> table, the amstrategies column is the
   number of strategies defined for this access method. For
   <acronym>B-tree</acronym>s, this number is 5.  These strategies
   correspond to -->

   新しいストラテジ集合の定義は本節の範囲ではありませんが、新しい演算子クラスを追加するために必要ですので、ここで<acronym>B-tree</acronym>ストラテジがどのように動作するかを説明することにします。<filename>pg_am</filename>テーブルにおいてamstrategies属性は、このアクセスメソッド用に定義されたストラテジの数を示します。<acronym>B-tree</acronym>では、この数は5です。これらのストラテジは、以下のように対応しています。
</para>

   <table tocentry="1">
    <!-- <title>B-tree Strategies</title>-->
    <title>B-treeストラテジ</title>
    <titleabbrev>B-tree</titleabbrev>
    <tgroup cols="2">
     <thead>
      <row>
       <!-- <entry>Operation</entry>
       <entry>Index</entry>-->
       <entry>演算</entry>
       <entry>インデックス</entry> 
      </row>
     </thead>
     <tbody>
      <row>
       <!-- <entry>less than</entry> -->
       <entry>より小さい</entry> 
       <entry>1</entry>
      </row>
      <row>
       <!-- <entry>less than or equal</entry> -->
       <entry>以下</entry>
       <entry>2</entry>
      </row>
      <row>
       <!-- <entry>equal</entry> -->
       <entry>等しい</entry>
       <entry>3</entry>
      </row>
      <row>
       <!-- <entry>greater than or equal</entry> -->
       <entry>以上</entry>
       <entry>4</entry>
      </row>
      <row>
       <!-- <entry>greater than</entry> -->
       <entry>より大きい</entry>
       <entry>5</entry>
      </row>
     </tbody>
    </tgroup>
   </table>

  <para>
   <!-- 
   The idea is that you'll need to add procedures corresponding to the
   comparisons above to the <filename>pg_amop</filename> relation (see below).
   The access method code can use these strategy numbers, regardless of data
   type, to figure out how to partition the <acronym>B-tree</acronym>,
   compute selectivity, and so on.  Don't worry about the details of adding
   procedures yet; just understand that there must be a set of these
   procedures for <filename>int2, int4, oid,</filename> and every other
   data type on which a <acronym>B-tree</acronym> can operate. -->

   考え方としては、上述の比較方法に対応する処理を、<filename>pg_amop</filename>リレーション（後述）に追加する必要があるということです。<acronym>B-tree</acronym>をどう分割するか、選択性をどう計算するかなどを見つけるために、アクセスメソッドのコードは、データ型にかかわらずこれらの戦略番号を使用することができます。処理を追加するための具体的な方法についてはまだ気にかけることはありません。<acronym>B-tree</acronym>が操作できるint2、int4、oidやその他のデータ型には、これらの処理が必要であるということを理解できればよいのです。

  </para>

  <para>
   <!-- 
   Sometimes, strategies aren't enough information for the system to figure
   out how to use an index.  Some access methods require other support
   routines in order to work. For example, the <acronym>B-tree</acronym>
   access method must be able to compare two keys and determine whether one
   is greater than, equal to, or less than the other.  Similarly, the
   <acronym>R-tree</acronym> access method must be able to compute
   intersections,  unions, and sizes of rectangles.  These
   operations do not correspond to user qualifications in
   SQL queries;  they are administrative routines used by
   the access methods, internally. -->

   ストラテジがシステムに対してインデックスを使う方法を見つけるのに十分な情報を持っていない場合もあります。アクセスメソッドの中には、その動作にその他のサポートルーチンが必要なものもあります。たとえば<acronym>B-tree</acronym>アクセスメソッドは、2つのキーを比較し、より大きいのか、等しいのか、より小さいのかを決定できなければいけません。同様に、<acronym>R-tree</acronym>アクセスメソッドは四角形の共通部分、和集合、交差の度合などを計算できなければいけません。これらの操作はSQLクエリにおけるユーザーが指定した条件とは対応しません。これらは内部的にアクセスメソッドが使用する管理ルーチンです。

  </para>

  <para>
   <!--  
   In order to manage diverse support routines consistently across all
   <productname>Postgres</productname> access methods,
   <filename>pg_am</filename> includes a column called
   <filename>amsupport</filename>.  This column records the number of
   support routines used by an access method.  For <acronym>B-tree</acronym>s,
   this number is one __ the routine to take two keys and return -1, 0, or
   +1, depending on whether the first key is less than, equal
   to, or greater than the second. -->

   すべての<productname>Postgres</productname>アクセスメソッドに対してさまざまなサポートルーチンを整合的に管理するために、<filename>pg_am</filename>は<filename>amsupport</filename>と呼ばれる列を含んでいます。この列は、1つのアクセスメソッドから使われるルーチンの数を持ちます。<acronym>B-tree</acronym>においてはこの数は1です。このルーチンは2つのキーを引数とし、最初のキーが2番目のキーより小さいか等しいか大きいかにより、それぞれ-1、0、+1を返します。
</para>

   <note>
    <para>
     <!--
     Strictly  speaking, this routine can return a negative
     number (&lt; 0), 0, or a non-zero positive number (&gt; 0). -->

     厳密にいうと、このルーチンは負数（&lt; 0）、0、0でない正数
     （&gt; 0）を返します。

    </para>
   </note>

  <para>
   <!-- 
   The <filename>amstrategies</filename> entry in <filename>pg_am</filename>
   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
   <filename>pg_am</filename>.  Similarly, <filename>amsupport</filename>
   is just the number of support routines required by  the  access
   method.  The actual routines are listed elsewhere. -->

   <filename>pg_am</filename>の<filename>amstrategies</filename>項目は、対象としているアクセスメソッド用に定義されたストラテジの数に過ぎません。「より小さい」、「以下」か、といった処理は<filename>pg_am</filename>には現れません。同様に、<filename>amsupport</filename>はアクセスメソッドが要求するサポートルーチンの数に過ぎません。実際のルーチンは別のところに定義されています。

  </para>

  <para>
   <!-- 
   By the way, the <filename>amorderstrategy</filename> entry tells whether
   the access method supports ordered scan.  Zero means it doesn't; if it
   does, <filename>amorderstrategy</filename> is the number of the strategy
   routine that corresponds to the ordering operator.  For example, btree
   has <filename>amorderstrategy</filename> = 1 which is its
   "less than" strategy number. -->

   ところで、<filename>amorderstrategy</filename>の項目はアクセスメソッドが順スキャンをサポートするかどうかを示します。0はサポートしないことを意味します。サポートする場合は<filename>amorderstrategy</filename>が順番の演算子と対応する戦略ルーチンの数になります。たとえば、btreeでは<filename>amorderstrategy</filename> = 1となっており、これは戦略番号「より小さい」のです。
  </para>

  <para>
   <!-- 
   The next table of interest is <filename>pg_opclass</filename>.  This table
   exists only to associate an operator class name and perhaps a default type
   with an operator class oid. Some existing opclasses are <filename>int2_ops,
   int4_ops,</filename> and <filename>oid_ops</filename>.  You need to add a
   row with your opclass name (for example,
   <filename>complex_abs_ops</filename>) to
   <filename>pg_opclass</filename>.  The <filename>oid</filename> of
   this row will be a foreign key in other tables, notably
   <filename>pg_amop</filename>. -->

   次に重要なテーブルは、<filename>pg_opclass</filename>です。このテーブルは演算子クラス名（と、場合によってはデフォルト型）を、演算子クラスのoidと関連付けるためだけに存在します。既存のopclassとして、<filename>int2_ops</filename>、<filename>int4_ops</filename>、<filename>oid_ops</filename>があります。自作のopclass名（たとえば<filename>complex_abs_ops</filename>）を持った行を<filename>pg_opclass</filename>に追加しなくてはいけません。この行の<filename>oid</filename>は他のテーブルにおける外部キーとなり、とくに<filename>pg_amop</filename>は重要です。
</para>

<programlisting>
INSERT INTO pg_opclass (opcname, opcdeftype)
    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
--------+-----------------+------------
 277975 | complex_abs_ops |     277946
(1 row)
</programlisting>

<para>
   <!--  
   Note that the oid for your <filename>pg_opclass</filename> 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. -->

   <filename>pg_opclass</filename>行のoidは違ったものであることに注意してください。しかし心配することはありません。この番号は型のoidを得たのと同じように後でシステムから得ることができます。</para>

  <para>
   <!-- 
   The above example assumes that you want to make this new opclass the
   default index opclass for the <filename>complex</filename> datatype.
   If you don't, just insert zero into <filename>opcdeftype</filename>,
   rather than inserting the datatype's oid: -->

   上記の例は、ユーザーがこの新しいopclassを<filename>complex</filename>データ型のデフォルトインデックスopclassにしようとしていると仮定します。そうでない場合は、<filename>opcdeftype</filename>にデータ型のoidを挿入するのではなく0を挿入してください。
</para>

<programlisting>
INSERT INTO pg_opclass (opcname, opcdeftype) VALUES ('complex_abs_ops', 0);
</programlisting>


  <para>
   <!-- So now we have an access method and an operator  class.
   We  still  need  a  set of operators.  The procedure for
   defining operators was discussed earlier in  this  manual.
   For  the  <filename>complex_abs_ops</filename>  operator  class on Btrees,
   the operators we require are: -->
 
   これでアクセスメソッドと演算子クラスができました。次に、演算子のセットが必要になります。演算子を定義する処理はこのマニュアルで前述しました。B-trees上の<filename>complex_abs_ops</filename>演算子では、以下の演算子が必要です。
</para>

<programlisting>
        absolute value less-than
        absolute value less-than-or-equal
        absolute value equal
        absolute value greater-than-or-equal
        absolute value greater-than
</programlisting>

  <para>
   <!-- Suppose the code that implements the functions  defined
   is stored in the file
   <filename>PGROOT/src/tutorial/complex.c</filename> -->

   定義された関数を実装するコードは、<filename>PGROOT/src/tutorial/complex.c</filename>に格納されているものとします。

  </para>

  <para>
   <!-- 
   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 <filename>complex.c</filename>
   or <filename>complex.source</filename> for the details.) -->

   Cコードの一部を以下に示します（この例の残りの部分では、イコール演算子のみを示すことにしますので注意してください。他の4つの演算子もよく似ています。詳細は、<filename>complex.c</filename>または<filename>complex.source</filename>を参照してください）。
</para>

<programlisting>
#define Mag(c) ((c)-&gt;x*(c)-&gt;x + (c)-&gt;y*(c)-&gt;y)

         bool
         complex_abs_eq(Complex *a, Complex *b)
         {
             double amag = Mag(a), bmag = Mag(b);
             return (amag==bmag);
         }
</programlisting>

  <para>
   <!-- We make the function known to Postgres like this: -->
   Postgresに関数を登録するために下記のようにします。
</para>

<programlisting>
CREATE FUNCTION complex_abs_eq(complex, complex)
              RETURNS bool
              AS 'PGROOT/tutorial/obj/complex.so'
              LANGUAGE 'c';
</programlisting>

  <para>
   <!-- There are some important things that are happening here. -->
   ここで重要なことがいくつかあります。
  </para>

  <para>
   <!-- 
   First, note that operators for less-than, less-than-or-equal, equal,
   greater-than-or-equal, and greater-than for <filename>complex</filename>
   are being defined.  We can only have one operator named, say, = and
   taking type <filename>complex</filename> for both operands.  In this case
   we don't have any other operator = for <filename>complex</filename>,
   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. -->

   まず、<filename>complex</filename>用の「より小さい」、「以下」、「等しい」、「以上」、「より大きい」のための演算子が定義されようとしているということです。たとえば、「=」という演算子は1つしかもつことができず、両方のオペランドを<filename>complex</filename>型とします。この場合<filename>complex</filename>に対するほかの演算子「=」はありません。しかしもし実用的なデータ型を構築するなら、おそらく「=」は複素数の通常の等しいという演算になってほしいかと思います。その場合は、complex_abs_eqに対しなにか他の演算子名を使う必要があります。
  </para>

  <para>
   <!-- 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 <filename>abs_eq</filename>.
   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.
   -->

  2番目に、Postgresの場合は、違った入力データ型であれば同じ名前の演算子を使うことができますが、Cではネームスペース内で1つのグローバルルーチンが使えるだけです。ですからC関数は<filename>abs_eq</filename>のような単純な名前にするべきではありません。通常はC関数名にデータ型名を入れておけば、他のデータ型の関数と衝突することもありません。
  </para>

  <para>
   <!-- 
   Third, we could have made the Postgres name of the function
   <filename>abs_eq</filename>, 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. -->

   3番目に、関数<filename>abs_eq</filename>のPostgres名は、Postgresが入力データ型によって同じ名前を持つ他のPostgres関数から区別してくれることを期待して作ることができます。ここでは例を簡単にするために、関数にCレベルとPostgresレベルで同じ名前を与えます。
  </para>

  <para>
   <!-- 
   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
   column of the <filename>pg_am</filename> table.  We will use this
   later on.  For now, ignore it. -->

   最後に、これらの演算子関数はブーリアンの値を返すことに注意してください。アクセスメソッドはこの事実に頼っています（一方で、サポート関数は、特定のアクセスメソッドが期待するものを何でも返します。この場合では符号付き整数です）。ファイルの最後のルーチンは、<filename>pg_am</filename>テーブルのamsupport列について説明したときに出てきた「サポートルーチン」です。これは後に使います。今のところは無視します。
  </para>

  <para>
   <!-- Now we are ready to define the operators: -->
   これで演算子を定義する準備ができました。
</para>

<programlisting>
CREATE OPERATOR = (
     leftarg = complex, rightarg = complex,
     procedure = complex_abs_eq,
     restrict = eqsel, join = eqjoinsel
         );
</programlisting>

<para>
   <!-- The important
   things here are the procedure names (which are the <acronym>C</acronym>
   functions defined above) and the restriction and join selectivity
   functions.  You should just use the selectivity functions used in
   the example (see <filename>complex.source</filename>).
   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. -->

   ここで重要なのは、プロシージャ名（つまり上記で定義される<acronym>C</acronym>関数）と制約と結合選択関数です。例で使われている選択関数を使ってください（<filename>complex.source</filename>を参照）。これらは「より小さい」、「等しい」、「以上」の場合に使われる関数とは違うことに注意してください。これらが供給されなければ、オプティマイザはインデックスを効果的に利用できません。

  </para>

  <para>
   <!-- The next step is to add entries for these operators to
   the <filename>pg_amop</filename> relation.  To do this,
   we'll need the <filename>oid</filename>s of the operators we just
   defined.  We'll look up the names of all the operators that take
   two <filename>complex</filename>es, and pick ours out: -->

   次のステップはこれらの演算子の項目を<filename>pg_amop</filename>リレーションに追加することです。そうするためには、上記で定義したばかりの演算子の<filename>oid</filename>が必要です。ここでは2つの<filename>complex</filename>を取るすべての演算子の名前を検索し、必要なものを選択します（ここでまた、<filename>oid</filename>番号はほぼ確実に違ったものになるでしょう）。
</para>

<programlisting>
    SELECT o.oid AS opoid, o.oprname
     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';

 opoid  | oprname
--------+---------
 277963 | +
 277970 | &lt;
 277971 | &lt;=
 277972 | =
 277973 | &gt;=
 277974 | &gt;
(6 rows)
</programlisting>

<para>
   <!-- 
   (Again, some of your <filename>oid</filename> numbers will almost
   certainly be different.)  The operators we are interested in are those
   with <filename>oid</filename>s 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. -->

   ここで重要な演算子は277970から277974までの<filename>oid</filename>をもつものです。得られる値はシステムによって異なるでしょうから、下記の値に置き換えてください。ここではSELECT文で行います。
  </para>

  <para>
   <!-- 
   Now we are ready to update <filename>pg_amop</filename> with our new
   operator class.  The most important thing in this entire discussion
   is that the operators are ordered, from less than through greater
   than, in <filename>pg_amop</filename>.  We add the rows we need:
   -->

   ここで、新しい演算子クラスで<filename>pg_amop</filename>を更新する準備ができました。この節全体で最も重要なことは、<filename>pg_amop</filename>の中では演算子は「より小さい」から「より大きい」への順番になっていることです。必要な行を追加します。
</para>

<programlisting>
    INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
        SELECT am.oid, opcl.oid, c.opoid, 1
        FROM pg_am am, pg_opclass opcl, complex_ops_tmp c
        WHERE amname = 'btree' AND
            opcname = 'complex_abs_ops' AND
            c.oprname = '&lt;';
</programlisting>

<para>
   <!-- 
   Now do this for the other operators substituting for the "1" in the
   third line above and the "&lt;" 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. -->

   すぐに他の演算子についても、上記の2行目の「1」と最終行の「&lt;」を置き換えて実行してください。順番に注意してください。「より小さい」が1、「以下」が2、「等しい」が3、「以上」が4、「より大きい」が5です。
  </para>

  <para>
   <!-- 
   The next step is registration of the "support routine" previously
   described in our discussion of <filename>pg_am</filename>.  The
   <filename>oid</filename> of this support routine is stored in the
   <filename>pg_amproc</filename> table, keyed by the access method
   <filename>oid</filename> and the operator class <filename>oid</filename>.
   First, we need to register the function in
   <productname>Postgres</productname> (recall that we put the
   <acronym>C</acronym> code that implements this routine in the bottom of
   the file in which we implemented the operator routines): -->

   次のステップは<filename>pg_am</filename>の説明で以前に説明された「サポートルーチン」の登録です。このサポートルーチンの<filename>oid</filename>は<filename>pg_amproc</filename>テーブルに格納され、アクセスメソッドの<filename>oid</filename>と演算子クラスの<filename>oid</filename>がキーになっています。まず始めに、この関数を<productname>Postgres</productname>に登録する必要があります（演算子ルーチンを実装したファイルの最後にこのルーチンを実装する<acronym>C</acronym>コードを入れたことを思い出してください）。
</para>

<programlisting>
    CREATE FUNCTION complex_abs_cmp(complex, complex)
     RETURNS int4
     AS 'PGROOT/tutorial/obj/complex.so'
     LANGUAGE 'c';

    SELECT oid, proname FROM pg_proc
     WHERE proname = 'complex_abs_cmp';

  oid   |     proname
--------+-----------------
 277997 | complex_abs_cmp
(1 row)
</programlisting>

<para>
   <!-- 
   (Again, your <filename>oid</filename> number will probably be different.)
   We can add the new row as follows: -->
   ここでまた、<filename>oid</filename>が違っているでしょう。下記のように新しい行を追加することができます。
</para>

<programlisting>
    INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
        SELECT a.oid, b.oid, c.oid, 1
            FROM pg_am a, pg_opclass b, pg_proc c
            WHERE a.amname = 'btree' AND
                b.opcname = 'complex_abs_ops' AND
                c.proname = 'complex_abs_cmp';
</programlisting>

  <para>
   <!-- 
   And we're done!  (Whew.)  It should now be possible to create
   and use btree indexes on <filename>complex</filename> columns. -->
   これで終わりです。これで<filename>complex</filename>列のB-treeインデックスを作って使用することが可能になったはずです。

  </para>

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