上で述べたように、 Postgres には 基本型(プログラミング言語で定義されています。)と複合型 (インスタンス)という 2 種類の型があります。この節からインデッ クスへのインタフェース節までで使用している例は、 complex.sql と complex.c にあります。複合型の例は funcs.sql にあります。
ユーザ定義型では、常に入力関数と出力関数が必要です。これらの 関数は、型が(ユーザによる入力とユーザへの出力のための)文字列中 にどうやって現れるか、またその型がメモリ中でどう構成されるかを 決定します。入力関数はその入力として NULL 終端文字列を取り、 その型の(メモリ中の)内部表現を返します。出力関数はその型の内部 表現を取り、NULL 終端文字列を返します。 ここで私たちは、複素数を表現する複素数型を定義したいとします。 私たちはごく自然に、
typedef struct Complex { double x; double y; } Complex;という C 構造体のようなメモリ中の複素数表現 と、外部文字列表現として (x,y) という形式の文字列を選びますよね。 これらの関数、特に出力関数を記述する事は困難ではありません。 しかしながら、いくつか忘れてはならない点があります。
外部(文字列)表現を定義する時には、当然の結果として、その表現の ための完全で堅牢なパーサを、入力関数として書かなければならない ことを忘れないでください。
Complex * complex_in(char *str) { double x, y; Complex *result; if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) { elog(WARN, "complex_in: error in parsing return NULL; } result = (Complex *)palloc(sizeof(Complex)); result->x = x; result->y = y; return (result); }出力関数は単に以下のようになるでしょう。
char * complex_out(Complex *complex) { char *result; if (complex == NULL) return(NULL); result = (char *) palloc(60); sprintf(result, "(%g,%g)", complex->x, complex->y); return(result); }
入出力関数は、各々の逆関数になるようにするべきです。 そうしないと、データをファイル(いや、たとえば他のコンピュータ上 にある別の誰かのデータベースでもいいです)にダンプしてまたそれを 戻そうとする時に、深刻な問題が発生するでしょう。これは、 浮動小数点数が含まれる際に特有な、一般的な問題です。
複素数(complex)型を定義するにあたり、その型 を生成する前に 2 つのユーザ定義関数 complex_in と complex_out を生成する必要があります。
CREATE FUNCTION complex_in(opaque) RETURNS complex AS 'PGROOT/tutorial/obj/complex.so' LANGUAGE 'c'; CREATE FUNCTION complex_out(opaque) RETURNS opaque AS 'PGROOT/tutorial/obj/complex.so' LANGUAGE 'c'; CREATE TYPE complex ( internallength = 16, input = complex_in, output = complex_out );
前に述べたように、Postgres は基本 型の配列を完全にサポートしています。これに加えて、 Postgres ではユーザ定義型の配列も サポートします。型を定義する時、Postgres は自動的にその型の配列のサポートを提供します。 歴史的な理由により、配列型はユーザ型の名前の前にアンダースコア 文字 _ が付いた名前になります。複合型の場合は、すでにシステム はそれらが内部的にどう見えるかを理解しているので、それらに対して 関数を定義する必要はありません。
ここまでに説明してきたのは、すべて "小さな" オブジェクトに関して だけです。小さいと言うのは、サイズが 8KB 以下のものをいいます。
Note: 1024 ロングワードは 8192 バイトです。実際は、型は 8192 バイトより かなり小さくなければなりません。これは、Postgres のタプルとページ・オーバーヘッドもこの 8KB という 制限に合うように調整されているからです。適合する実際の値は マシンのアーキテクチャに依存します。