まずlibpqを使用するための環境を整えた.で,接続しないと何にもできないので,libpqを使用してPostgreSQLへ接続する方法を調査してみた.
環境構築
サンプル
接続関数PQconnectdb
接続情報の取得
切断
環境構築
Debian GNU/Linuxを使用している私は以下をした.
apt-get install libpgsql2 postgresql-dev
他の環境ではどうしたらよいのかは知らない.とりあえず以下があればよい(たぶん).
libpq-fe.h
私のマシンでは以下にあった.
/usr/include/postgresql/libpq-fe.h
libpq.so
私のマシンでは以下にあった.
/usr/lib/libpq.so
サンプル
libpqでPostgreSQLに接続するプログラムでの処理概要は以下となる.
PostgreSQLに接続
PostgreSQLに要求
切断
本頁では,もっともPostgreSQLへの接続方法のうち,もっとも基本的なものと切断方法について記述する.また,DB接続プログラムでのもっとも基本的な注意点として,接続状態や接続情報の取得,チェックがある.これらの方法についても記述する.以下はPostgreSQLに接続して接続情報を取得,表示し,切断するサンプルである.
#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
int
main (int argc, char **argv)
{
/* PostgreSQLとのコネクション */
PGconn *connection;
int status;
char *dbInfo;
if (argc != 2)
{
fprintf (stderr, "Usage : %s conninfo\n", argv[0]);
exit (EXIT_FAILURE);
}
else
{
printf ("conninfo : %s\n", argv[1]);
}
/* 接続 */
connection = PQconnectdb (argv[1]);
if (connection == NULL)
{
printf ("PQconnectdb failed\n");
exit (EXIT_FAILURE);
}
/* 接続要求結果のチェック */
status = PQstatus (connection);
switch (status)
{
case CONNECTION_OK:
printf ("connect success\n");
break;
case CONNECTION_BAD:
printf ("connect failed\n");
/* PostgreSQLからのエラーメッセージを表示 */
if ((dbInfo = PQerrorMessage (connection)) != NULL)
{
printf ("error message : %s\n", dbInfo);
}
exit (EXIT_FAILURE);
default:
printf ("unexcept\n");
exit (EXIT_FAILURE);
}
/* 接続情報の取得 */
/* 当該接続のデータベース名 */
if ((dbInfo = PQdb (connection)) != NULL)
{
printf ("DBname : %s\n", dbInfo);
}
/* 当該接続のユーザ名 */
if ((dbInfo = PQuser (connection)) != NULL)
{
printf ("DBuser : %s\n", dbInfo);
}
/* 当該接続のパスワード */
if ((dbInfo = PQpass (connection)) != NULL)
{
printf ("DBpasswd : %s\n", dbInfo);
}
/* 当該接続のサーバホスト名 */
if ((dbInfo = PQhost (connection)) != NULL)
{
printf ("DBhost : %s\n", dbInfo);
}
/* 当該接続のポート番号 */
if ((dbInfo = PQport (connection)) != NULL)
{
printf ("DBport : %s\n", dbInfo);
}
/* 当該接続のデバッグ用tty */
if ((dbInfo = PQtty (connection)) != NULL)
{
printf ("Debug tty : %s\n", dbInfo);
}
/* 当該接続のバックエンドオプション */
if ((dbInfo = PQoptions (connection)) != NULL)
{
printf ("options : %s\n", dbInfo);
}
/* PostgreSQLバックエンドのPID */
printf ("PID : %d\n", PQbackendPID (connection));
/* 切断 */
PQfinish (connection);
exit (EXIT_SUCCESS);
}
これをコンパイルするには,ヘッダとライブラリの指定が必要である.
gcc -I/usr/include/postgresql/ -lpq connect.c
このサンプルは引数にあるDB接続情報を使用してPostgreSQLに接続する.以下は実行結果.
$> ./a.out "host=dbserver user=matsu password=hogefuga dbname=firstdb"
conninfo : host=dbserver user=matsu password=hogefuga dbname=firstdb
connect success
DBname : firstdb
DBuser : matsu
DBpasswd : hogefuga
DBhost : dbserver
DBport : 5432
Debug tty :
options :
PID : 1825
$> ./a.out "host=dbserver user=matsu password=hogefuga"
conninfo : host=dbserver user=matsu password=hogefuga
connect failed
error message : FATAL 1: No pg_hba.conf entry for host 192.168.69.1, user matsu, database matsu
$> ./a.out "host=dbserver user=nobody password=hogefuga dbname=firstdb"
conninfo : host=dbserver user=nobody password=hogefuga dbname=firstdb
connect failed
error message : FATAL 1: Password authentication failed for user "nobody"
$> ./a.out "host=dbserver user=matsu password=nopass dbname=firstdb"
conninfo : host=dbserver user=matsu password=nopass dbname=firstdb
connect failed
error message : FATAL 1: Password authentication failed for user "matsu"
サーバ側ではsyslogなどにログが出力されているので,疑い深い人はそちらも確かめた方がよいかもしれない.たぶんこんな感じで出ている(頁の表示上の都合で,\で改行してある).
Feb 23 15:51:39 dbserver postgres[1825]: [1] DEBUG: \
connection: host=xxx.xxx.xxx.xxx user=matsu database=firstdb
Feb 23 15:51:46 dbserver postgres[1826]: [1] FATAL 1: \
No pg_hba.conf entry for host xxx.xxx.xxx.xxx, user matsu, database matsu
Feb 23 15:51:55 dbserver postgres[1827]: [1] FATAL 1: \
Password authentication failed for user "nobody"
Feb 23 15:52:07 dbserver postgres[1829]: [1] FATAL 1: \
Password authentication failed for user "matsu"
接続関数PQconnectdb
libpqには,いくつかのDB接続関数がある.前節のサンプルでは以下を使用した.
PGconn *PQconnectdb(const char *conninfo)
引数は一つのcharへのポインタであり,先述の実行例のようにスペース区切りで
キーワード=値
を繋げたものである.主なキーワードは以下である.
host
DBサーバ名
hostaddr
DBサーバのIPアドレス
user
DB接続時のユーザ名
password
userに対するパスワード
dbname
DB名
PQconnectDBは内部でPGconnの領域を確保し,それへのポインタを返す.NULLを返すのは,PGconnへの領域確保に失敗した場合のみで,接続に失敗しても返す.PGconnはサーバへの接続情報であり,これによりサーバに対して複数接続し管理することができるようになっている.PGconnは直接操作,参照してはいけない(普通にはできないようになっている).接続状態は以下で取得する.
ConnStatusType PQstatus(const PGconn *conn)
返り値には多くのパターンがあるが,同期接続を行なうPQconnectdbの場合(※)は以下の二種類がある.
CONNECTION_OK
正常
CONNECTION_BAD
異常
PQconnectDBを実行したあと,さまざまな要求をサーバに投げる前には,PQstatusで接続情報を確認する必要がある.
※ サーバへの接続要求が(成功,失敗を問わず)完了するまでブロックする.
接続情報の取得
PGconnには接続状況だけでなく,サーバやユーザ名などの接続情報が格納されている.PGconnの内部は直接参照できないので,取り出したい情報に応じた関数を使用する.以下に上記のサンプルで使用した接続情報取得関数の一覧を示す.
サーバからのエラーメッセージ
以下の関数は,引数で渡す接続においてサーバから最後に取得したDB操作のエラーメッセージを返す.
char PQerrorMessage(const PGconn conn);
接続ユーザ名
以下の関数は,引数で渡す接続でのユーザ名を返す.
char *PQuser(const PGconn *conn)
接続パスワード
以下の関数は,引数で渡す接続で使用したパスワードを返す.
char *PQpass(const PGconn *conn)
接続サーバ名
以下の関数は,引数で渡す接続の接続先サーバ名を返す.
char *PQhost(const PGconn *conn)
接続ポート
以下の関数は,引数で渡す接続の接続ポートを返す.
char *PQport(const PGconn *conn)
デバッグ用tty
以下の関数は,引数で渡す接続の,デバッグ用ttyを返す.
char *PQtty(const PGconn *conn)
バックエンドオプション
以下の関数は,引数で渡す接続の,バックエンドオプションを返す.
char *PQoptions(const PGconn *conn)
バックエンドのPID
以下の関数は,引数で渡す接続の,バックエンドのPIDを返す.
int PQbackendPID(const PGconn *conn);
この値は,サーバ側で調査をする際に有用である.
切断
PostgreSQLに接続したら切断する.これには以下の関数を使用する.
void PQfinish(PGconn *conn)
この関数により,引数で渡した接続を切断し,PQconnectDBで確保したPGconnの領域も開放する.