pgtypesライブラリはPostgreSQLデータベースの型をCプログラムで使用できるようにC言語に対応させます また、これらの型を使用したCの基本的な計算を行う関数も提供します。 この計算には、PostgreSQL サーバを使用しません。 以下の例を参照してください。
EXEC SQL BEGIN DECLARE SECTION; date date1; timestamp ts1, tsout; interval iv1; char *out; EXEC SQL END DECLARE SECTION; PGTYPESdate_today(&date1); EXEC SQL SELECT started, duration INTO :ts1, :iv1 FROM datetbl WHERE d=:date1; PGTYPEStimestamp_add_interval(&ts1, &iv1, &tsout); out = PGTYPEStimestamp_to_asc(&tsout); printf("Started + duration: %s\n", out); free(out);
数値型では、任意の精度での計算機能を提供します。
PostgreSQLサーバにおける対応する型については項8.1を参照してください。
任意精度を持つために、この変数は動的に拡張、縮小できなければなりません。
これが、PGTYPESnumeric_new
やPGTYPESnumeric_free
関数では、ヒープ領域上にのみしか変数を作成できない理由です。
10進数も似ていますが精度が限定されていますので、ヒープ領域以外にスタック領域上でも作成可能です。
以下の関数は数値型で稼動させることができます。
PGTYPESnumeric_new
新規割当ての数値型へのポインタを要求します。
numeric *PGTYPESnumeric_new(void);
PGTYPESnumeric_free
数値型を解放し、そのメモリをすべて解放します。
void PGTYPESnumeric_free(numeric *var);
PGTYPESnumeric_from_asc
文字列表記から数値型に変換します。
numeric *PGTYPESnumeric_from_asc(char *str, char **endptr);
有効な書式の例を示します。 -2、.794、+3.44、592.49E07、-32.84e-4。 値への変換に成功した場合、有効なポインタが返されます。 失敗した場合はヌルポインタが返されます。 現在ecpgは文字列全体を解析しますので、まだ*endptrに最初の無効な文字の場所を格納しません。 このためendptrを安全にヌルにすることができます。
PGTYPESnumeric_to_asc
数値型numの文字列表現を持つ、malloc
で割り当てられた文字列へのポインタを返します。
char *PGTYPESnumeric_to_asc(numeric *num, int dscale);
数値は、必要に応じて四捨五入され、dscale10進桁数で出力されます。
PGTYPESnumeric_add
2つの数値変数を加算し、3番目の数値変数に格納します。
int PGTYPESnumeric_add(numeric *var1, numeric *var2, numeric *result);
この関数は変数var1と変数var2に加算し、その結果をresultに格納します。 成功時0を、エラー時-1を返します。
PGTYPESnumeric_sub
2つの数値型変数を減算し、3番目の数値型変数に結果を格納します。
int PGTYPESnumeric_sub(numeric *var1, numeric *var2, numeric *result);
この関数は変数var1から変数var2を差し引きます。 演算結果は変数var3に格納します。 成功時0を、エラー時-1を返します。
PGTYPESnumeric_mul
2つの数値型変数を乗算し、3番目の数値型変数に結果を格納します。
int PGTYPESnumeric_mul(numeric *var1, numeric *var2, numeric *result);
この関数は変数var1と変数var2を掛け合わせます。 演算結果は変数var3に格納します。 成功時0を、エラー時-1を返します。
PGTYPESnumeric_div
2つの数値型変数で除算し、3番目の数値型変数に結果を格納します。
int PGTYPESnumeric_div(numeric *var1, numeric *var2, numeric *result);
この関数は変数var1を変数var2で割ります。 演算結果は変数var3に格納します。 成功時0を、エラー時-1を返します。
PGTYPESnumeric_cmp
2つの数値型変数を比較します。
int PGTYPESnumeric_cmp(numeric *var1, numeric *var2)
この関数は2つの数値型変数を比較します。 エラーの場合INT_MAXが帰ります。 成功時、この関数は以下のいずれかを返します。
var1がvar2より大きければ1。
var1がvar2より小さければ-1。
var1がvar2と等しければ0。
PGTYPESnumeric_from_int
int型変数を数値型に変換します。
int PGTYPESnumeric_from_int(signed int int_val, numeric *var);
この関数は符号付整数型の変数を受付け、数値型変数var内に格納します。 成功時0、失敗時-1が返ります。
PGTYPESnumeric_from_long
long int型変数を数値型変数に変換します。
int PGTYPESnumeric_from_long(signed long int long_val, numeric *var);
この関数は符号付long int型の変数を受付け、数値型変数var内に格納します。 成功時0、失敗時-1が返ります。
PGTYPESnumeric_copy
数値型変数を他の数値型変数に複製します。
int PGTYPESnumeric_copy(numeric *src, numeric *dst);
この関数は、srcが指し示す変数の値をdstが指し示す変数に複製します。 成功時0、失敗時-1が返ります。
PGTYPESnumeric_from_double
double型の変数を数値型変数に変換します。
int PGTYPESnumeric_from_double(double d, numeric *dst);
この関数はdouble型の変数を受付け、変換結果をdstが指し示す変数内に格納します。 成功時0、失敗時-1が返ります。
PGTYPESnumeric_to_double
数値型変数をdouble型に変換します。
int PGTYPESnumeric_to_double(numeric *nv, double *dp)
この関数はnvが指し示す数値型変数の値をdpが指し示すdouble型変数に変換します。 成功時0、オーバーフローを含むエラーが発生した時-1が返ります。 オーバーフローが発生した場合はさらに、大域変数errnoはPGTYPES_NUM_OVERFLOWに設定されます。
PGTYPESnumeric_to_int
数値型変数をint型に変換します。
int PGTYPESnumeric_to_int(numeric *nv, int *ip);
この関数はnvが指し示す数値型変数の値をipが指し示す整数型変数に変換します。 成功時0、オーバーフローを含むエラーが発生した時-1が返ります。 オーバーフローが発生した場合はさらに、大域変数errnoはPGTYPES_NUM_OVERFLOWに設定されます。
PGTYPESnumeric_to_long
数値型変数をlong型に変換します。
int PGTYPESnumeric_to_long(numeric *nv, long *lp);
この関数はnvが指し示す数値型変数の値をlpが指し示すlong変数に変換します。 成功時0、オーバーフローを含むエラーが発生した時-1が返ります。 オーバーフローが発生した場合はさらに、大域変数errnoはPGTYPES_NUM_OVERFLOWに設定されます。
PGTYPESnumeric_to_decimal
数値型変数を10進数型に変換します。
int PGTYPESnumeric_to_decimal(numeric *src, decimal *dst);
この関数はsrcが指し示す数値型変数の値をdstが指し示すlong変数に変換します。 成功時0、オーバーフローを含むエラーが発生した時-1が返ります。 オーバーフローが発生した場合はさらに、大域変数errnoはPGTYPES_NUM_OVERFLOWに設定されます。
PGTYPESnumeric_from_decimal
10進数型変数を数値型に変換します。
int PGTYPESnumeric_from_decimal(decimal *src, numeric *dst);
この関数はsrcが指し示す10進数型変数の値をdstが指し示す数値型変数に変換します。 成功時0、むエラーが発生した時-1が返ります。 10進数型は制限付の数値型として実装されていますので、この変換ではオーバーフローは起きません。
Cのデータ型を使用して、プログラムからSQL型のデータを取り扱うことができます。 PostgreSQLサーバにおける対応する型については項8.5を参照してください。
データ型を操作するために以下の関数を使用することができます。
PGTYPESdate_from_timestamp
タイムスタンプから日付部分を取り出します。
date PGTYPESdate_from_timestamp(timestamp dt);
この関数は唯一の引数としてタイムスタンプを受付け、そこから日付部分を取り出します。
PGTYPESdate_from_asc
テキスト表現から日付型に変換します。
date PGTYPESdate_from_asc(char *str, char **endptr);
この関数はCのchar*型文字列strとCのchar*型文字列endptrへのポインタを受付けます。 現在ecpgは文字列全体を解析しますので、まだ*endptrに最初の無効な文字の場所を格納しません。 このためendptrを安全にヌルにすることができます。
この関数が常にMDY書式の日付を前提としている点に注意してください。 現在ecpgにはこれを変更するための変数がありません。
以下の入力書式が可能です。
表 31-1. 有効なPGTYPESdate_from_asc
の入力書式
入力 | 結果 |
---|---|
January 8, 1999 | January 8, 1999 |
1999-01-08 | January 8, 1999 |
1/8/1999 | January 8, 1999 |
1/18/1999 | January 18, 1999 |
01/02/03 | February 1, 2003 |
1999-Jan-08 | January 8, 1999 |
Jan-08-1999 | January 8, 1999 |
08-Jan-1999 | January 8, 1999 |
99-Jan-08 | January 8, 1999 |
08-Jan-99 | January 8, 1999 |
08-Jan-06 | January 8, 2006 |
Jan-08-99 | January 8, 1999 |
19990108 | ISO 8601; January 8, 1999 |
990108 | ISO 8601; January 8, 1999 |
1999.008 | year and day of year |
J2451187 | Julian day |
January 8, 99 BC | year 99 before the Common Era |
PGTYPESdate_to_asc
日付型変数のテキスト表現を返します。
char *PGTYPESdate_to_asc(date dDate);
この関数は唯一の引数として日付型dDateを受付けます。 この関数は1999-01-18、つまりYYYY-MM-DD書式で日付を出力します。
PGTYPESdate_julmdy
日付型の変数から、日、月、年の値を取り出します。
void PGTYPESdate_julmdy(date d, int *mdy);
この関数は日付型のdと、3つの整数値を持つ配列mdyへのポインタを受付けます。 この変数名はその並びを表し、mdy[0]には月数、mdy[1]には日数が、mdy[2]には年が入ります。
PGTYPESdate_mdyjul
日付の日、月、年を指定した3つの整数からなる配列から日付値を作成します。
void PGTYPESdate_mdyjul(int *mdy, date *jdate);
この関数は、1番目の引数として3つの整数からなる配列(mdy)、2番目の引数として処理結果を格納する日付型の変数へのポインタを受付けます。
PGTYPESdate_dayofweek
日付値から週内日数を表す数を返します。
int PGTYPESdate_dayofweek(date d);
この関数は唯一の引数として日付型変数dを受付け、その日付の週内日数を表す整数を返します。
0 - 日曜日
1 - 月曜
2 - 火曜日
3 - 水曜日
4 - 木曜日
5 - 金曜日
6 - 土曜日
PGTYPESdate_today
現在の日付を返します。
void PGTYPESdate_today(date *d);
この関数は現在の日付に設定される日付型変数(d)を指し示すポインタを受付けます。
PGTYPESdate_fmt_asc
日付型変数を書式マスクを使用したテキスト表現に変換します。
int PGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf);
この関数は変換対象の日付(dDate)、書式マスク(fmtstring)、日付のテキスト表現を格納するための文字列(outbuf)を受付けます。
成功時に0、エラーが発生した場合は負の値が返ります。
以下のリテラルを使用して、フィールドを指定することができます。
dd - 月内の日数。
mm - 年内の月数。
yy - 二桁表記の年数
yyyy - 四桁表記の年数
ddd - 日の名前(省略形)
mmm - 月の名前(省略形)
他の文字はすべて出力文字列にそのまま複製されます。
以下の表に幾つか書式の例を示します。 この関数の使用法に関するアイディアを提供しています。 出力行はすべて1959年11月23日に基づいています。
PGTYPESdate_defmt_asc
書式マスクを使用してCのchar*文字列から日付型の値に変換します。
int PGTYPESdate_defmt_asc(date *d, char *fmt, char *str);
この関数は、処理結果を格納するための日付型へのポインタ(d)、日付を解析するための書式マスク(fmt)、日付のテキスト表現を含むCのchar*文字列(str)を受付けます。 テキスト表現は書式マスクに合った表現であることが仮定されています。 しかし、文字列と書式マスクを1:1に対応付けする必要はありません。 この関数は並んだ順番に解析し、年の位置を表すyyまたはyyyyを、月の位置を表すmmを、日の位置を表すddを検索します。
以下の表に書式の例をいくつか示します。 この関数の使用方法に関するアイディアを提供します。
表 31-3. 有効なrdefmtdate
の入力書式
fmt | str | 結果 |
---|---|---|
ddmmyy | 21-2-54 | 1954-02-21 |
ddmmyy | 2-12-54 | 1954-12-02 |
ddmmyy | 20111954 | 1954-11-20 |
ddmmyy | 130464 | 1964-04-13 |
mmm.dd.yyyy | MAR-12-1967 | 1967-03-12 |
yy/mm/dd | 1954, February 3rd | 1954-02-03 |
mmm.dd.yyyy | 041269 | 1969-04-12 |
yy/mm/dd | In the year 2525, in the month of July, mankind will be alive on the 28th day | 2525-07-28 |
dd-mm-yy | I said on the 28th of July in the year 2525 | 2525-07-28 |
mmm.dd.yyyy | 9/14/58 | 1958-09-14 |
yy/mm/dd | 47/03/29 | 1947-03-29 |
mmm.dd.yyyy | oct 28 1975 | 1975-10-28 |
mmddyy | Nov 14th, 1985 | 1985-11-14 |
Cのタイムスタンプ型を使用してプログラムからSQLのタイムスタンプ型データを扱うことができます。 PostgreSQLにおける対応する型については 項8.5 を参照してください。
以下の関数を使用してタイムスタンプ型を扱うことができます。
PGTYPEStimestamp_from_asc
テキスト表現のタイムスタンプをタイムスタンプ型変数に変換します。
timestamp PGTYPEStimestamp_from_asc(char *str, char **endptr);
この関数は変換対象の文字列(str)とC char*へのポインタ(endptr)を受付けます。 現在ecpgは文字列全体を解析しますので、まだ*endptrに最初の無効な文字の場所を格納しません。 このためendptrを安全にヌルにすることができます。
この関数は成功時変換後のタイムスタンプを返します。 エラー時、PGTYPESInvalidTimestampが返され、errnoがPGTYPES_TS_BAD_TIMESTAMPに設定されます。 この値についての重要な注意書きについてPGTYPESInvalidTimestampを参照してください。
通常、入力文字列には許される日付指定の任意の組み合わせ、空白文字、許される時間指定を含むことができます。 タイムスタンプはecpgでサポートされていない点に注意してください。 変換することはできますが、例えばPostgreSQLサーバが行うような計算を行うことはできません。 時間帯指定は無視されます。
以下の表に入力文字列の例をいくつか示します。
PGTYPEStimestamp_to_asc
日付をC char*文字列に変換します。
char *PGTYPEStimestamp_to_asc(timestamp tstamp);
この関数はタイムスタンプtstampを唯一の引数として受付け、タイムスタンプのテキスト表現を含む割り当てられた文字列を返します。
PGTYPEStimestamp_current
現在のタイムスタンプを取り出します。
void PGTYPEStimestamp_current(timestamp *ts);
この関数は現在のタイムスタンプを取り出し、ts が指し示すタイムスタンプ型変数に格納します。
PGTYPEStimestamp_fmt_asc
書式マスクを使用してタイムスタンプ型変数をC char*に変換します。
int PGTYPEStimestamp_fmt_asc(timestamp *ts, char *output, int str_len, char *fmtstr);
この関数は、最初の引数として変換対象のタイムスタンプ(ts)を、出力バッファのポインタ(output)、出力バッファで割当て可能な最大長 (str_len)、変換に使用する書式マスク(fmtstr)を受付けます。
成功するとこの関数は0を返します。 エラーが発生した場合は負の値が返ります。
書式マスクには以下の書式指定を使用することができます。
書式指定はlibcのstrftime
関数で使用されるものと同じです。
書式指定以外は出力バッファに複製されます。
%A - 各言語の曜日名称に置換されます。
%a - 各言語の曜日略称に置換されます。
%B - 各言語の月名称に置換されます。
%b - 各言語の月略称に置換されます。
%C - 年を100で割った10進数に置換されます。1桁の場合は先頭に0が付与されます。
%c - 各言語の日付時刻表現に置換されます。
%D - %m/%d/%yと同じです。
%d - 月内の10進日数(01-31)に置換されます。
%E* %O* - POSIXロケール拡張です。 %Ec %EC %Ex %EX %Ey %EY %Od %Oe %OH %OI %Om %OM %OS %Ou %OU %OV %Ow %OW %Oy という並びは別の表現を提供するものと仮定されています。
さらに、%OBは、(日に関する仕様がない単体で使用される)別の月名を表すものとして実装されています。
%e - 月内10進日数(1-31)に置換されます。1桁の場合は前に空白が付けられます。
%F - %Y-%m-%dと同じです。
%G - 世紀付の10進数として年に置換されます。 この年は週の部分がより多く含まれます。(月曜が週の最初の日です。)
%g -%G同様年に置換されますが、世紀の分がない10進数(00-99)です。
%H - 10進の時間(24時間単位)に置換されます(00-23)。
%h - %bと同じです。
%I - 10進の時間(12時間単位)に置換されます(01-12)。
%j - 10進の年内日数に置換されます(001-366)。
%k - 10進の時間(24時間単位)に置換されます(0-23)。1桁の場合は先頭に空白が付けられます。
%l - 10進の時間(12時間単位)に置換されます(1-12)。1桁の場合は先頭に空白が付けられます。
%M - 10進の分数に置換されます(00-59)。
%m -10進の月数に置換されます(01-12)。
%n - 改行に置換されます。
%O* - %E*と同じです。
%p - 各言語の"午前"または"午後"に適切に置換されます。
%R - %H:%Mと同じです。
%r - %I:%M:%S %pと同じです。
%S - 10進の秒数に置換されます(00-60)。
%s - エポック、UTCからの秒数に置換されます。
%T - %H:%M:%Sと同じです。
%t - タブに置換されます。
%U - 10進の週番号(日曜が週の先頭です)に置換されます。
%u - 10進の週番号(月曜が週の先頭です)に置換されます。
%V - 10進の年内の週番号(月曜が週の先頭です)に置換されます(01-53)。 新しい年で、1月1日を含む週が4日以上存在する場合、その週が1となります。 さもなくば、この週は前年の週となり、次の週が1となります。
%v - %e-%b-%Yと同じです。
%W - 10進の年内の週番号(月曜が週の先頭です)に置換されます(00-53)。
%w - 10進の週内日数(日曜が週の先頭です)に置換されます(0-6)。
%X - 各言語の時間表現に置換されます。
%x - 各言語の日付表現に置換されます。
%Y - 10進の世紀付年に置換されます。
%y - 10進の世紀なし年に置換されます(00-99)。
%Z - 時間帯名称に置換されます。
%z - UTCからの時間帯オフセットに置換されます。 UTCより東では正符号が先頭に付き、西では負符号が付きます。 それぞれ2桁の時間と分がその後に続きますが、その区切りはありません。(この形式はRFC 822の日付ヘッダでよく使用されます。)
%+ - 各言語の日付時刻表現に置換されます。
%-* - GNU libc拡張です。数値出力を行う際に何も文字を詰めません。
$_* - GNU libcの拡張です。明示的に空白文字を使用して文字を詰めます。
%0* - GNU libcの拡張です。明示的に0を使用して文字を詰めます。
%% - %に置換されます。
PGTYPEStimestamp_sub
タイムスタンプの減算を行い、その結果を時間間隔方の変数に格納します。
int PGTYPEStimestamp_sub(timestamp *ts1, timestamp *ts2, interval *iv);
この関数はts1が指し示すタイムスタンプ型変数からts2が指し示すタイムスタンプ型変数を差し引き、ivが指し示す時間間隔型変数に結果を格納します。
成功すると、この関数は0を返し、エラーが発生した場合は負の値を返します。
PGTYPEStimestamp_defmt_asc
書式マスクを使用して、テキスト表現からタイムスタンプ値を変換します。
int PGTYPEStimestamp_defmt_asc(char *str, char *fmt, timestamp *d);
この関数はstr変数内に格納されたタイムスタンプのテキスト表現、fmt変数内に格納された使用される書式マスクを受付けます。 結果はdが指し示す変数内に格納されます。
書式マスクfmtがヌルならば、この関数はデフォルトの書式マスク%Y-%m-%d %H:%M:%Sを使用するようになります。
これは PGTYPEStimestamp_fmt_asc
関数の逆です。
使用できる書式マスク項目についてはその文書を参照してください。
PGTYPEStimestamp_add_interval
タイムスタンプ型変数に時間間隔型変数を加算します。
int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout);
この関数は、タイムスタンプ型変数tinへのポインタと時間間隔型変数spanへのポインタを受付けます。これは、時間間隔値をタイムスタンプ値に加算し、その結果のタイムスタンプ値をtoutが指し示す変数に格納します。
成功すると、この関数は0を返します。エラーが発生した場合は負の値を返します。
PGTYPEStimestamp_sub_interval
タイムスタンプ型変数から時間間隔型変数を引き去ります。
int PGTYPEStimestamp_sub_interval(timestamp *tin, interval *span, timestamp *tout);
この関数はtinが指し示すタイムスタンプ型変数からspanが指し示す時間間隔型変数を引きます。 結果はtoutが指し示す変数に保存されます。
成功するとこの関数は0を、エラーが発生した場合は負の値を返します。
Cにおける時間間隔型によりプログラムからSQLの時間間隔型のデータを扱うことができます。 PostgreSQLサーバにおける対応する型については項8.5を参照してください。
以下の関数を使用して、時間間隔型を扱うことができます。
PGTYPESinterval_new
新しく割り当てた時間間隔型変数へのポインタを返します。
interval *PGTYPESinterval_new(void);
PGTYPESinterval_free
以前に割り当てられた時間間隔型変数のメモリを解放します。
void PGTYPESinterval_new(interval *intvl);
PGTYPESinterval_from_asc
テキスト表現から時間間隔型に変換します。
interval *PGTYPESinterval_from_asc(char *str, char **endptr);
この関数は入力文字列strを変換し、割当てられた時間間隔型へのポインタを返します。 現在ecpgは文字列全体を解析しますので、まだ*endptrに最初の無効な文字の場所を格納しません。 このためendptrを安全にヌルにすることができます。
PGTYPESinterval_to_asc
時間間隔型変数をテキスト表現に変換します。
char *PGTYPESinterval_to_asc(interval *span);
この関数はspanが指し示す時間間隔型変数をC char*に変換します。 出力は@ 1 day 12 hours 59 mins 10 secsのようになります。
PGTYPESinterval_copy
時間間隔型変数を複製します。
int PGTYPESinterval_copy(interval *intvlsrc, interval *intvldest);
この関数は、intvlsrcが指し示す時間間隔型変数を intvldestが指し示す変数に複製します。 事前に格納先の変数用のメモリを割り当てる必要があることに注意してください。
10進数型は数値型に似ています。 しかし、その最大精度は30有効桁に制限されています。 ヒープ上にしか作成できない数値型と比べ、10進数型はスタックまたはヒープ上に作成することができます。 (このためにはPGTYPESdecimal_new()およびPGTYPESdecimal_free()関数を使用します。) 項31.9で説明するInformix互換モードでは10進数型を扱う関数がより多く存在します。
以下の関数を使用して、10進数型を扱うことができます。 これらはlibcompatライブラリに含まれるものだけではありません。
PGTYPESdecimal_new
新しく割り当てられた10進数型変数へのポインタを要求します。
decimal *PGTYPESdecimal_new(void);
PGTYPESdecimal_free
10進数型を解放し、そのメモリをすべて解放します。
void PGTYPESdecimal_free(decimal *var);
引数は数値型変数(または数値型変数へのポインタ)を含まなければなりません。 しかし実際のメモリ上の表現は無効です。
オーバーフローが発生しました。 数値型はほぼ任意精度を扱うことができますので、数値型変数から他の型への変換ではオーバーフローが発生する可能性があります。
アンダーフローが発生しました。 数値型はほぼ任意精度を扱うことができますので、数値型変数から他の型への変換ではオーバーフローが発生する可能性があります。
0除算が試行されました。
無効なタイムスタンプを表すタイムスタンプ型の値です。
これはPGTYPEStimestamp_from_asc
関数において解析エラーが発生した場合に返されます。
タイムスタンプデータ型の内部表現のため、PGTYPESInvalidTimestampは同時に有効なタイムスタンプでもあります。
これは1899-12-31 23:59:59と設定されています。
エラーを検出するためには、アプリケーションでPGTYPESInvalidTimestampを検査するだけでなく、各PGTYPEStimestamp_from_asc
呼び出し後にerrno != 0も検査してください。