31.9. Informix互換モード

ecpgをInformix 互換モードというモードで動作させることができます。 このモードが有効ならば、Informix E/SQL用のInformixプリプロセッサであるかのように動作します。 一般的にいうと、これにより埋め込みSQLコマンドを導入する際にEXEC SQLプリミッティブの代わりにドル印を使用することができます。

   $int j = 3;
   $CONNECT TO :dbname;
   $CREATE TABLE test(i INT PRIMARY KEY, j INT);
   $INSERT INTO test(i, j) VALUES (7, :j);
   $COMMIT;

INFORMIX、INFORMIX_SEという2つの互換モードがあります。

互換モードを使用するプログラムをリンクする際、ecpgに同梱されるlibcompatとリンクすることを忘れないでください。

以前に説明した構文上の飾りの他に、 Informix互換モードでは、入力、出力、データ変換関数、E/SQLからecpgで既知の埋め込みSQL文変換関数も移植しています。

Informix互換モードはecpgのpgtypeslibライブラリと密接に関係しています。 pgtypeslibはSQLデータ型とCホストプログラム内のデータ型を対応付けし、ほとんどのInformix互換モードで追加された関数を使用してこれらのCホストプログラム型を操作することができます。 しかし、互換範囲は制限されています これはInformixの動作を真似ることはしません。 これを使用して、多少は同じ名前で同じ基本動作を行う関数を操作、提供できますが、Informixを使用しているのであれば、完全な置き換えにはなりません。 さらに、一部のデータ型は異なります。 例えば、PostgreSQL'sの日付時刻や時間間隔型ではYEAR TO MINUTEのような範囲を持ちませんので、これらはecpgではサポートできないことが判ります。

31.9.1. 追加の埋め込みSQL文

CLOSE DATABASE

この文は現在の接続を閉じます。 実際、これはecpgのDISCONNECT CURRENTと同義です。

    $CLOSE DATABASE;                /* close the current connection */
    EXEC SQL CLOSE DATABASE;

31.9.2. 追加関数

decadd

2つの10進数型変数を加算します。

int decadd(decimal *arg1, decimal *arg2, decimal *sum);

この関数は、10進数型の最初の演算項目(arg1)へのポインタ、10進数型の2番目の演算項目(arg2)へのポインタ、加算結果を格納する10進数型値(sum)へのポインタを受付けます。 成功すると、この関数は0を返します。 オーバーフローが発生した場合はECPG_INFORMIX_NUM_OVERFLOWが、アンダーフローの場合はECPG_INFORMIX_NUM_UNDERFLOWが返ります。 この他の失敗が発生した場合は-1が返り、errnoにはpgtypeslibにおける対応するerrno番号が設定されます。

deccmp

2つの10進数型変数を比較します。

int deccmp(decimal *arg1, decimal *arg2);

この関数は、最初の10進数値(arg1)へのポインタ、2番目の10進数値(arg2)へのポインタを受付け、どちらが大きいかを示す整数値を返します。

  • arg1が指し示す値がarg2が指し示す値より大きければ1。

  • arg1が指し示す値がarg2が指し示す値より小さければ-1。

  • arg1が指し示す値とarg2が指し示す値が同じならば0。

deccopy

10進数値を複製します。

void deccopy(decimal *src, decimal *target);

この関数は、最初の引数として複製元の10進数値(src)へのポインタ、2番目の引数として10進数型の複製先構造体(target)へのポインタを受付けます。

deccvasc

ASCII表現から10進数型に値を変換します。

int deccvasc(char *cp, int len, decimal *np);

この関数は、変換対象の文字列表現を持つ文字列(cp)へのポインタとその文字列長lenを受付けます。 npはこの操作結果を格納する10進数型の値へのポインタです。

有効な書式の例は以下の通りです。 -2.794+3.44592.49E07-32.84e-4

この関数は成功時0を返します。 オーバーフローやアンダーフローが発生した場合はECPG_INFORMIX_NUM_OVERFLOWECPG_INFORMIX_NUM_UNDERFLOWが返されます。 ASCII表現の解析ができなかった場合はECPG_INFORMIX_BAD_NUMERICが、指数部分の解析に問題がある場合はECPG_INFORMIX_BAD_EXPONENTが返されます。

deccvdbl

double型の値を10進数型の値に変換します。

int deccvdbl(double dbl, decimal *np);

この関数は、最初の引数として変換対象のdouble型の変数(dbl)を受付けます。 2番目の引数(np)として、この関数は操作結果を格納する10進数型変数へのポインタを受付けます。

この関数は成功時に0を返します。 変換が失敗した場合は負の値が返ります。

deccvint

int型の値を10進数型の値に変換します。

int deccvint(int in, decimal *np);

この関数は最初の引数として、変換対象のint型変数(in)を受付けます。 2番目の引数(np)として、この関数は変換結果を格納する10進数型変数へのポインタを受付けます。

この関数は成功時に0を返します。 変換が失敗した場合は負の値が返ります。

deccvlong

long型の値を10進数型の値に変換します。

int deccvlong(long lng, decimal *np);

この関数は最初の引数として、変換対象のlong型変数(lng)を受付けます。 2番目の引数(np)として、この関数は変換結果を格納する10進数型変数へのポインタを受付けます。

この関数は成功時に0を返します。 変換が失敗した場合は負の値が返ります。

decdiv

2つの10進数型変数の除算を行います。

int decdiv(decimal *n1, decimal *n2, decimal *result);

この関数は、1番目の演算項目(n1)と2番目の演算項目(n2)となる変数のポインタを受付け、n1/n2を計算します。 resultは、操作結果を格納する変数へのポインタです。

成功時0が返され、除算の失敗時には負の値が返されます。 オーバーフローやアンダーフローが発生した場合、この関数はそれぞれECPG_INFORMIX_NUM_OVERFLOWECPG_INFORMIX_NUM_UNDERFLOWを返します。 0割りが発生した場合は、ECPG_INFORMIX_DIVIDE_ZEROが返されます。

decmul

2つの10進数型変数を乗算します。

int decmul(decimal *n1, decimal *n2, decimal *result);

この関数は、1番目の演算項目(n1)と2番目の演算項目(n2)となる変数のポインタを受付け、n1*n2を計算します。 resultは、操作結果を格納する変数へのポインタです。

成功時0が返され、除算の失敗時には負の値が返されます。 オーバーフローやアンダーフローが発生した場合、この関数はそれぞれECPG_INFORMIX_NUM_OVERFLOWECPG_INFORMIX_NUM_UNDERFLOWを返します。

decsub

10進数型値同士の引算を行います。

int decsub(decimal *n1, decimal *n2, decimal *result);

この関数は、1番目の演算項目(n1)と2番目の演算項目(n2)となる変数のポインタを受付け、n1-n2を計算します。 resultは、操作結果を格納する変数へのポインタです。

成功時0が返され、除算の失敗時には負の値が返されます。 オーバーフローやアンダーフローが発生した場合、この関数はそれぞれECPG_INFORMIX_NUM_OVERFLOWECPG_INFORMIX_NUM_UNDERFLOWを返します。

dectoasc

10進数型変数をC char* 文字列のASCII表現に変換します。

int dectoasc(decimal *np, char *cp, int len, int right)

この関数は10進数型変数(np)のポインタを受け付け、テキスト表現に変換します。 cp は変換結果を格納するためのバッファです。 rightパラメータは、10進数小数点の右側の何桁を出力するかを指定します。 結果はこの10進桁数で丸められます。 rightを-1にすることで、すべての有効な桁数が出力されるようになります。 lenで示す出力バッファ長が、最後のNUL文字を含むテキスト表現を格納するのには不十分であった場合、結果には*という1文字が格納され、-1が返されます。

この関数は、cpバッファが小さすぎる場合に-1を返します。 メモリ不足の場合はECPG_INFORMIX_OUT_OF_MEMORYを返します。

dectodbl

10進数型変数をdoubleに変換します。

int dectodbl(decimal *np, double *dblp);

この関数は変換対象の10進数型変数(np)のポインタと処理結果を格納するdouble変数(dblp)へのポインタを受け付けます。

成功時0が、変換失敗時負の値が返されます。

dectoint

10進数型変数を整数型に変換します。

int dectoint(decimal *np, int *ip);

この関数は変換対象の10進数型変数(np)のポインタと処理結果を格納する整数型変数(lp)へのポインタを受け付けます。

成功時0が、変換失敗時負の値が返されます。 オーバーフローが発生した場合はECPG_INFORMIX_NUM_OVERFLOWが返されます。

このecpgの実装はInformixの実装と異なることに注意してください。 Informixでは、整数範囲に-32767から32767までという制限をしていますが、ecpgでの制限はアーキテクチャに依存(-INT_MAX .. INT_MAX)します。

dectolong

10進数型変数をlong型に変換します。

int dectolong(decimal *np, long *lngp);

この関数は変換対象の10進数型変数(np)のポインタと処理結果を格納するlong変数(lngp)へのポインタを受け付けます。

成功時0が、変換失敗時負の値が返されます。 オーバーフローが発生した場合はECPG_INFORMIX_NUM_OVERFLOWが返されます。

このecpgの実装はInformixの実装と異なることに注意してください。 Informixでは、整数範囲に-2,147,483,647から2,147,483,647までという制限をしていますが、ecpgでの制限はアーキテクチャに依存(-LONG_MAX .. LONG_MAX)します。

rdatestr

日付をC char*文字列に変換します。

int rdatestr(date d, char *str);

この関数は2つの引数を受付けます。 最初の引数は変換対象の日付 (d)、2番目は変換後の文字列へのポインタです。 出力書式は常にyyyy-mm-ddですので、少なくとも11文字(ヌル終端を含む)を結果文字列に割り当てなければなりません。

この関数は成功時0を、エラー時負の値を返します。

このecpgの実装はInformixの実装と異なることに注意してください。 Informixでは、環境変数により書式を変更できますが、ecpgでは出力書式を変更することはできません。

rstrdate

日付のテキスト表現を解析します。

int rstrdate(char *str, date *d);

この関数は、変換対象の日付のテキスト表現(str)と日付型変数のポインタ(d)を受付けます。 この関数では書式マスクを指定することができません。 Informixのデフォルトの書式マスクであるmm/dd/yyyyを使用します。 内部的には、この関数はrdefmtdateを使用して実装しています。 したがって、rstrdateは速くありません。 もし選択肢があるのであれば、書式マスクを明示的に指定することができるrdefmtdateを選択すべきです。

この関数はrdefmtdateと同様の値を返します。

rtoday

現在の日付を入手します。

void rtoday(date *d);

この関数は日付型変数d)へのポインタを受付け、そこに現在の日付を格納します。

内部的には、この関数はPGTYPESdate_today関数を使用します。

rjulmdy

日付型変数から、日、月、年の値を取り出します。

int rjulmdy(date d, short mdy[3]);

この関数は日付d、3つのshort integer型の値からなる配列mdyを受付けます。 この変数名はその並びを表し、mdy[0]には月数、mdy[1]には日数が、mdy[2]には年が入ります。

現在この関数は常に0を返します。

内部的にはこの関数はPGTYPESdate_julmdy関数を使用します。

rdefmtdate

書式マスクを使用して、文字列を日付型の値に変換します。

int rdefmtdate(date *d, char *fmt, char *str);

この関数は、処理結果を格納するための日付型へのポインタ(d)、日付を解析するための書式マスク(fmt)、日付のテキスト表現を含むCのchar*文字列(str)を受付けます。 テキスト表現は書式マスクに合った表現であることが仮定されています。 しかし、文字列と書式マスクを1:1に対応付けする必要はありません。 この関数は並んだ順番に解析し、年の位置を表すyyまたはyyyyを、月の位置を表すmmを、日の位置を表すddを検索します。

この関数は以下の値を返します。

  • 0 - 関数が正常に愁傷しました。

  • ECPG_INFORMIX_ENOSHORTDATE - 日付に、日、月、年を区切る文字がありませんでした。 この場合、入力文字列は6バイト、8バイトのいずれかでなければなりませんが、そうではありませんでした。

  • ECPG_INFORMIX_ENOTDMY - 書式文字列が正しく、年月日の順番を示していません。

  • ECPG_INFORMIX_BAD_DAY - 入力文字列に有効な日が含まれていません。

  • ECPG_INFORMIX_BAD_MONTH - 入力文字列に有効な月が含まれていません。

  • ECPG_INFORMIX_BAD_YEAR - 入力文字列に有効な年が含まれていません。

内部的には、この関数はxref linkend="PGTYPESdatedefmtasc">関数を使用して実装しています。 この関数の説明には、入力例の表がありますので、こちらも参照してください。

rfmtdate

書式マスクを使用して日付型変数をテキスト表現に変換します。

int rfmtdate(date d, char *fmt, char *str);

この関数は変換対象の日付(d)、書式マスク(fmt)、日付のテキスト表現を格納する文字列(str)を受付けます。

成功時0、エラーが発生した場合は負の値が返されます。

内部的にはこの関数はPGTYPESdate_fmt_asc関数を使用します。 例が記載されていますので、こちらも参照してください。

rmdyjul

日付の日、月、年を表す3つのshort integers型からなる配列から日付型の値を作成します。

int rmdyjul(short mdy[3], date *d);

この関数は3つのshort integers型からなる配列(mdy)と処理結果を格納する日付型変数へのポインタを受付けます。

現在この関数は常に0を返します。

内部的にはこの関数はPGTYPESdate_mdyjul関数を使用して実装しています。

rdayofweek

日付型の値の週内日数を示す値を返します。

int rdayofweek(date d);

この関数は日付型変数dをその唯一の引数として受付け、その日付の週内日数を示す整数を返します。

  • 0 - 日曜

  • 1 - 月曜

  • 2 - 火曜

  • 3 - 水曜

  • 4 - 木曜

  • 5 - 金曜

  • 6 - 土曜

内部的にはこの関数は PGTYPESdate_dayofweek関数を使用して実装しています。

dtcurrent

現在のタイムスタンプを取り出します。

void dtcurrent(timestamp *ts);

この関数は現在のタイムスタンプを受け取り、tsが指し示すタイムスタンプ型変数に格納します。

dtcvasc

ANSI標準で記載されたテキスト表現をタイムスタンプ型変数に変換します。

int dtcvasc(char *str, timestamp *ts);

この関数は対象の文字列(str)と処理結果を格納するタイムスタンプ型変数(ts)へのポインタを受付けます。

この関数は成功時0を返し、エラー時負の値を返します。

内部的にはこの関数はPGTYPEStimestamp_from_asc関数を使用します。 入力例の表がありますので、こちらも参照してください。

dtcvfmtasc

書式マスクを使用してANSI標準で記載されたテキスト表現をタイムスタンプ型変数に変換します。

dtcvfmtasc(char *inbuf, char *fmtstr, timestamp *dtvalue)

この関数は、対象とする文字列(inbuf)、使用する書式マスク(fmtstr)、処理結果を格納するタイムスタンプ変数(ts)へのポインタを受付けます。

この関数はPGTYPEStimestamp_defmt_ascを使用して実装されています。 使用可能な書式指定のリストがありますので、こちらも参照してください。

この関数は成功時に0を、エラー時負の値を返します。

dtsub

タイムスタンプ型同士で減算を行い、時間間隔型変数を返します。

int dtsub(timestamp *ts1, timestamp *ts2, interval *iv);

この関数はts1が指し示すタイムスタンプ型変数からts2が指し示すタイムスタンプ型変数を引き去ります。 結果はivが指し示す時間間隔型変数に格納されます。

成功時この関数は0を返し、エラー時負の値を返します。

dttoasc

タイムスタンプ型変数をC char*文字列に変換します。

int dttoasc(timestamp *ts, char *output);

この関数は対象のタイムスタンプ型変数(ts)へのポインタ、処理結果を格納する文字列(output)を受付けます。 これはtsをANSI 標準SQLに従うテキスト表現(YYYY-MM-DD HH:MM:SSとして定義)に変換します。

成功時この関数は0を返し、エラー時負の値を返します。

dttofmtasc

書式マスクを使用してタイムスタンプ型変数をC char*に変換します。

int dttofmtasc(timestamp *ts, char *output, int str_len, char *fmtstr);

この関数は、最初の引数として変換対象のタイムスタンプ(ts)を、出力バッファのポインタ(output)、出力バッファで割当て可能な最大長 (str_len)、変換に使用する書式マスク(fmtstr)を受付けます。

成功時この関数は0を返します。エラーが発生した場合は負の値を返します。

内部的に、この関数はPGTYPEStimestamp_fmt_asc関数を使用します。 使用できる書式マスクに関する情報がありますので、こちらも参照してください。

intoasc

時間間隔型変数をC char*文字列に変換します。

int intoasc(interval *i, char *str);

この関数は、変換対象の時間間隔型変数(i)へのポインタ、処理結果を格納する文字列(str)を受付けます。 これはiをANSI 標準SQLにおけるテキスト表現(YYYY-MM-DD HH:MM:SSとして定義)に変換します。

成功時、この関数は0を返します。 エラーが発生した場合は負の値を返します。

rfmtlong

long integer値を書式マスクを使用してテキスト表現に変換します。

int rfmtlong(long lng_val, char *fmt, char *outbuf);

この関数は、long型の値 lng_val、書式マスクfmt、出力バッファoutbufへのポインタを受付けます。 これはlong型の値を書式マスクに従ってテキスト表現に変換します。

書式マスクは以下の書式指定文字を組み合わせることができます。

  • * (アスタリスク) - この位置が空白ならばアスタリスクで埋めます。

  • & (アンパサンド) - この位置が空白ならば0で埋めます。

  • # - 先頭のゼロを空白に変換します。

  • < - 文字列内で数値を左そろえします。

  • , (カンマ) - 4桁以上の数値をカンマで区切った3桁にグループ化します。

  • . (ピリオド) - この文字は数値から小数部分を区別します。

  • - (マイナス) - 数値が負の場合、マイナス記号を付けます。

  • + (プラス) - 数値が正の場合プラス記号を付けます。

  • ( - これは負の値の先頭のマイナス記号を置き換えます。 マイナス記号は現れません。

  • ) - この文字はマイナス記号を置き換え、負の値の最後に出力します。

  • $ - 通貨記号

rupshift

文字列を大文字に変換します。

void rupshift(char *str);

この関数は文字列へのポインタを受付け、すべての小文字を大文字に変換します。

byleng

文字列内の文字数を返します。 ただし、末尾の空白は数えません。

int byleng(char *str, int len);

この関数は最初の引数として、固定長の文字列(str)を、2番目の引数としてその文字列長 (len)想定しています。 これは、文字列から末尾の空白を取り除いた、有効文字の数を返します。

ldchar

固定長の文字列をヌル終端の文字列に複製します。

void ldchar(char *src, int len, char *dest);

この関数は複製対象の固定長の文字列(src)、文字列長(len)、格納先メモリ(dest)へのポインタを受付けます。 destが指し示す文字列には少なくともlen+1バイトを割り当てなければならない点に注意してください。 この関数は多くてもlenバイトを新しい場所に複製します。 (元の文字列が末尾に空白文字を持つ場合に少なくなります。) そして、ヌル終端を付与します。

rgetmsg

int rgetmsg(int msgnum, char *s, int maxsize);

この関数は存在しますが、現在実装されていません。

rtypalign

int rtypalign(int offset, int type);

この関数は存在しますが、現在実装されていません。

rtypmsize

int rtypmsize(int type, int len);

この関数は存在しますが、現在実装されていません。

rtypwidth

int rtypwidth(int sqltype, int sqllen);

この関数は存在しますが、現在実装されていません。

rsetnull

変数にNULLを設定します。

int rsetnull(int t, char *ptr);

この関数は、変数の種類を示す整数とC char*にキャストした変数自体へのポインタを受付けます。

以下の種類が存在します。

  • CCHARTYPE - charまたは char*型の変数用

  • CSHORTTYPE - short int型の変数用

  • CINTTYPE - int型の変数用

  • CBOOLTYPE - boolean型の変数用

  • CFLOATTYPE - float型の変数用

  • CLONGTYPE - long型の変数用

  • CDOUBLETYPE - double型の変数用

  • CDECIMALTYPE - decimal型の変数用

  • CDATETYPE - date型の変数用

  • CDTIMETYPE - timestamp型の変数用

以下にこの関数の呼び出し例を示します。

$char c[] = "abc       ";
$short s = 17;
$int i = -74874;

rsetnull(CCHARTYPE, (char *) c);
rsetnull(CSHORTTYPE, (char *) &s);
rsetnull(CINTTYPE, (char *) &i);

risnull

変数がNULLか検査します。

int risnull(int t, char *ptr);

この関数は検査する変数の種類(t)、変数(ptr)へのポインタを受付けます。 後者はchar*にキャストする必要があることに注意してください。 取り得る変数種類については rsetnull関数を参照してください。

この関数の使用方法の例を示します。

$char c[] = "abc       ";
$short s = 17;
$int i = -74874;

risnull(CCHARTYPE, (char *) c);
risnull(CSHORTTYPE, (char *) &s);
risnull(CINTTYPE, (char *) &i);

31.9.3. 追加の定数

ここで示す定数はすべてエラーを示すものであり、負の値を表すように定義されていることに注意してください。 また、他の定数の説明では、現在の実装で定数が表す数値がわかります。 しかし、この数値に依存してはなりません。 しかし、これらのすべてが負の値であることに依存することは可能です。

ECPG_INFORMIX_NUM_OVERFLOW

計算時にオーバーフローが発生した場合、関数はこの値を返します。 内部的には-1200(Informixの定義)と定義されています。

ECPG_INFORMIX_NUM_UNDERFLOW

計算時にアンダーフローが発生した場合、関数はこの値を返します。 内部的には-1201(Informixの定義)と定義されています。

ECPG_INFORMIX_DIVIDE_ZERO

計算時に0割りが発生した場合、関数はこの値を返します。 内部的には-1202(Informixの定義)と定義されています。

ECPG_INFORMIX_BAD_YEAR

日付の解析時に年の値が不正であった場合、関数はこの値を返します。 内部的には-1204(Informixの定義)と定義されています。

ECPG_INFORMIX_BAD_MONTH

日付の解析時に月の値が不正であった場合、関数はこの値を返します。 内部的には-1205(Informixの定義)と定義されています。

ECPG_INFORMIX_BAD_DAY

日付の解析時に日の値が不正であった場合、関数はこの値を返します。 内部的には-1206(Informixの定義)と定義されています。

ECPG_INFORMIX_ENOSHORTDATE

解析処理が短縮日付表現を必要にしているが、正しい長さの日付文字列が得られなかった場合、関数はこの値を返します。 内部的には-1209(Informixの定義)と定義されています。

ECPG_INFORMIX_DATE_CONVERT

関数はこの値を返します。 内部的には-1210(Informixの定義)と定義されています。

ECPG_INFORMIX_OUT_OF_MEMORY

関数はこの値を返します。 内部的には-1211(Informixの定義)と定義されています。

ECPG_INFORMIX_ENOTDMY

解析処理が書式マスク(mmddyyのような)が存在することを前提としているが、すべてのフィールドが正しく列挙されていない場合、関数はこの値を返します。 内部的には-1212(Informixの定義)と定義されています。

ECPG_INFORMIX_BAD_NUMERIC

解析処理がエラーのため数値のテキスト表現を解析できなかった場合や数値変数の少なくとも1つが無効のため数値変数を使用した計算を完了できなかった場合、関数はこの値を返します。 内部的には-1213(Informixの定義)と定義されています。

ECPG_INFORMIX_BAD_EXPONENT

関数はこの値を返します。 内部的には-1216(Informixの定義)と定義されています。

ECPG_INFORMIX_BAD_DATE

関数はこの値を返します。 内部的には-1218(Informixの定義)と定義されています。

ECPG_INFORMIX_EXTRA_CHARS

関数はこの値を返します。 内部的には-1264(Informixの定義)と定義されています。