23
8月
2007

接続

まず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の領域も開放する.

You may also like...