/*
* testlibpq.c : Postgres フロントエンドライブラリ Libpq
* C バージョンのテスト
*
*
*/
#include <stdio.h>
#include "libpq-fe.h"
void
exit_nicely(PGconn *conn)
{
PQfinish(conn);
exit(1);
}
main()
{
char *pghost,
*pgport,
*pgoptions,
*pgtty;
char *dbName;
int nFields;
int i,
j;
/* FILE *debug; */
PGconn *conn;
PGresult *res;
/*
* バックエンドとの接続に必要なパラメータをセットしてプログラムを
* 開始します.
* パラメータが NULL であれば,環境変数を探して妥当と思われる値を
* 使おうとしますが,見つからない場合は,システムデフォルトの定数
* を使います.
*/
pghost = NULL; /* バックエンドが動作しているサーバのホスト名 */
pgport = NULL; /* バックエンドのポート番号 */
pgoptions = NULL; /* バックエンドのスタートアップオプション */
pgtty = NULL; /* バックエンドのデバッグ用 tty */
dbName = "template1";
/* データベースへ接続 */
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/*
* バックエンドとの接続が成功したことを確認
*/
if (PQstatus(conn) == CONNECTION_BAD)
{
fprintf(stderr, " データベース '%s' への接続に失敗しました \n", dbName);
fprintf(stderr, "%s", PQerrorMessage(conn));
exit_nicely(conn);
}
/* debug = fopen("/tmp/trace.out","w"); */
/* PQtrace(conn, debug); */
/* トランザクションブロックの開始 */
res = PQexec(conn, "BEGIN");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "BEGIN コマンドの実行に失敗しました \n");
PQclear(res);
exit_nicely(conn);
}
/*
* メモリリークを防ぐため,必要がなくなったら,すぐに
* PQclear(PGresult) しましょう
*/
PQclear(res);
/*
* データベースのシステムカタログ,pg_database からインスタンスを
* 取り出す
*/
res = PQexec(conn, "DECLARE mycursor CURSOR FOR select * from pg_database");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "DECLARE CURSOR コマンドの実行に失敗しました \n");
PQclear(res);
exit_nicely(conn);
}
PQclear(res);
res = PQexec(conn, "FETCH ALL in mycursor");
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "FETCH ALL コマンドがタプルを正しく返しませんでした \n");
PQclear(res);
exit_nicely(conn);
}
/* まず属性名を表示 */
nFields = PQnfields(res);
for (i = 0; i < nFields; i++)
printf("%-15s", PQfname(res, i));
printf("\n\n");
/* 次にインスタンスを表示 */
for (i = 0; i < PQntuples(res); i++)
{
for (j = 0; j < nFields; j++)
printf("%-15s", PQgetvalue(res, i, j));
printf("\n");
}
PQclear(res);
/* カーソルを閉じる */
res = PQexec(conn, "CLOSE mycursor");
PQclear(res);
/* トランザクションをコミット */
res = PQexec(conn, "COMMIT");
PQclear(res);
/* データベースとの接続を閉じ,後始末 */
PQfinish(conn);
/* fclose(debug); */
}
/*
* testlibpq2.c : 非同期通知インターフェースのテスト
*
* まずこのプログラムを実行し,それから他のウィンドウで psql から
*
* NOTIFY TBL2;
*
* としてみてください.
*
* もうちょっと凝ってみたい場合は,次のようにします.
* まず以下のようなデータベースをつくります.
*
* CREATE TABLE TBL1 (i int4);
*
* CREATE TABLE TBL2 (i int4);
*
* CREATE RULE r1 AS ON INSERT TO TBL1 DO
* (INSERT INTO TBL2 values (new.i); NOTIFY TBL2);
*
* そして
*
* INSERT INTO TBL1 values (10);
*
* としてください.
*
*/
#include <stdio.h>
#include "libpq-fe.h"
void
exit_nicely(PGconn *conn)
{
PQfinish(conn);
exit(1);
}
main()
{
char *pghost,
*pgport,
*pgoptions,
*pgtty;
char *dbName;
int nFields;
int i,
j;
PGconn *conn;
PGresult *res;
PGnotify *notify;
/*
* バックエンドとの接続に必要なパラメータをセットしてプログラムを
* 開始します.
* パラメータが NULL であれば,環境変数を探して妥当と思われる値を
* 使おうとしますが,見つからない場合は,システムデフォルトの定数
* を使います.
*
*/
pghost = NULL; /* バックエンドが動作しているサーバのホスト名 */
pgport = NULL; /* バックエンドのポート番号 */
pgoptions = NULL; /* バックエンドのスタートアップオプション */
pgtty = NULL; /* バックエンドのデバッグ用 tty */
dbName = getenv("USER"); /* これは読者のテスト用データベースの名前に
適宜置き換えてください */
/* データベースへ接続 */
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/*
* バックエンドとの接続が成功したことを確認
*/
if (PQstatus(conn) == CONNECTION_BAD)
{
fprintf(stderr, " データベース '%s' への接続に失敗しました \n", dbName);
fprintf(stderr, "%s", PQerrorMessage(conn));
exit_nicely(conn);
}
res = PQexec(conn, "LISTEN TBL2");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "LISTEN コマンドの実行に失敗しました \n");
PQclear(res);
exit_nicely(conn);
}
/*
* メモリリークを防ぐため,必要がなくなったら,すぐに
* PQclear(PGresult) しましょう
*/
PQclear(res);
while (1)
{
/*
* チェックの繰り返しの間,ちょっとだけウエイトを入れます.
* select() ではウエイトを入れると効率的です.
*/
sleep(1);
/* バックエンドの非同期メッセージを取り込む */
PQconsumeInput(conn);
/* 非同期通知メッセージのチェック */
while ((notify = PQnotifies(conn)) != NULL)
{
fprintf(stderr,
" 非同期通知 '%s' を PID '%d' のバックエンドから受けました \n",
notify->relname, notify->be_pid);
free(notify);
}
}
/* データベースとの接続を閉じ,後始末 */
PQfinish(conn);
}
/*
* testlibpq3.c : Postgres フロントエンドライブラリ Libpq
* C バージョンのテスト
* バイナリカーソルのテスト
*
*
* まず以下のようなデータベースをつくります.
*
* CREATE TABLE test1 (i int4, d float4, p polygon);
*
* INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0,
* 2.0)'::polygon);
*
* INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0,
* 1.0)'::polygon);
*
* 出力は以下のようになるはずです:
*
*
* タプル 0:
* i = ( 4 バイト ) 1,
* d = ( 4 バイト ) 3.567000,
* p = ( 68 バイト ) 座標数 2 境界ボックス = (hi=3.000000,4.000000,
* lo = 1.000000,2.000000)
* タプル 1:
* i = ( 4 バイト ) 2,
* d = ( 4 バイト ) 89.050003,
* p = ( 68 バイト ) 座標数 2 境界ボックス = (hi=4.000000,3.000000,
* lo = 2.000000,1.000000)
*
*/
#include <stdio.h>
#include "postgres.h"
#include "libpq-fe.h"
#include "utils/geo_decls.h" /* POLYGON 型を使うのに必要 */
void
exit_nicely(PGconn *conn)
{
PQfinish(conn);
exit(1);
}
main()
{
char *pghost,
*pgport,
*pgoptions,
*pgtty;
char *dbName;
int nFields;
int i,
j;
int i_fnum,
d_fnum,
p_fnum;
PGconn *conn;
PGresult *res;
/*
* バックエンドとの接続に必要なパラメータをセットしてプログラムを
* 開始します.
* パラメータが NULL であれば,環境変数を探して妥当と思われる値を
* 使おうとしますが,見つからない場合は,システムデフォルトの定数
* 使います.
*
*/
pghost = NULL; /* バックエンドが動作しているサーバのホスト名 */
pgport = NULL; /* バックエンドのポート番号 */
pgoptions = NULL; /* バックエンドのスタートアップオプション */
pgtty = NULL; /* バックエンドのデバッグ用 tty */
dbName = getenv("USER"); /* これは読者のテスト用データベースの名前に
適宜置き換えてください */
/* データベースへ接続 */
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/*
* バックエンドとの接続が成功したことを確認
*/
if (PQstatus(conn) == CONNECTION_BAD)
{
fprintf(stderr, " データベース '%s' への接続に失敗しました \n", dbName);
fprintf(stderr, "%s", PQerrorMessage(conn));
exit_nicely(conn);
}
/* トランザクションブロックの開始 */
res = PQexec(conn, "BEGIN");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "BEGIN コマンドの実行に失敗しました \n");
PQclear(res);
exit_nicely(conn);
}
/*
* メモリリークを防ぐため,必要がなくなったら,すぐに
* PQclear(PGresult) しましょう
*/
PQclear(res);
/*
* データベースのシステムカタログ,pg_database からインスタンスを
* 取り出す
*/
res = PQexec(conn, "DECLARE mycursor BINARY CURSOR FOR select * from test1");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "DECLARE CURSOR コマンドの実行に失敗しました \n");
PQclear(res);
exit_nicely(conn);
}
PQclear(res);
res = PQexec(conn, "FETCH ALL in mycursor");
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "FETCH ALL コマンドがタプルを正しく返しませんでした \n");
PQclear(res);
exit_nicely(conn);
}
i_fnum = PQfnumber(res, "i");
d_fnum = PQfnumber(res, "d");
p_fnum = PQfnumber(res, "p");
for (i = 0; i < 3; i++)
{
printf("type[%d] = %d, size[%d] = %d\n",
i, PQftype(res, i),
i, PQfsize(res, i));
}
for (i = 0; i < PQntuples(res); i++)
{
int *ival;
float *dval;
int plen;
POLYGON *pval;
/*
* テーブル上の三つのフィールドの型はわかっているので
* ここでは変数に直接結び付けます
*/
ival = (int *) PQgetvalue(res, i, i_fnum);
dval = (float *) PQgetvalue(res, i, d_fnum);
plen = PQgetlength(res, i, p_fnum);
/*
* plen はフィールド長の分を含んでいないので,VARHDSZ を
* 加えます
*/
pval = (POLYGON *) malloc(plen + VARHDRSZ);
pval->size = plen;
memmove((char *) &pval->npts, PQgetvalue(res, i, p_fnum), plen);
printf(" タプル %d:\n", i);
printf(" i = ( %d バイト ) %d,\n",
PQgetlength(res, i, i_fnum), *ival);
printf(" d = ( %d バイト ) %f,\n",
PQgetlength(res, i, d_fnum), *dval);
printf(" p = ( %d バイト ) 座標数 %d \t 境界ボックス = (hi=%f,%f, lo = %f,%f)\n",
plen,
pval->npts,
pval->boundbox.high.x,
pval->boundbox.high.y,
pval->boundbox.low.x,
pval->boundbox.low.y);
}
PQclear(res);
/* カーソルを閉じる */
res = PQexec(conn, "CLOSE mycursor");
PQclear(res);
/* トランザクションをコミット */
res = PQexec(conn, "COMMIT");
PQclear(res);
/* データベースとの接続を閉じ,後始末 */
PQfinish(conn);
}