第 27章libpq - C ライブラリ

目次
27.1. データベース接続制御関数
27.2. 接続状態関数
27.3. コマンド実行関数
27.3.1. メイン関数
27.3.2. 問い合わせ結果の情報の取り出し
27.3.3. 他のコマンド用の結果情報の取り出し
27.3.4. SQLコマンドに含めるための文字列のエスケープ処理
27.3.5. SQLコマンドに含めるためのバイナリ文字列のエスケープ処理
27.4. 非同期コマンドの処理
27.5. 近道インタフェース
27.6. 非同期通知
27.7. COPYコマンド関連関数
27.7.1. COPYデータ送信用関数
27.7.2. COPYデータ受信用関数
27.7.3. 廃れた COPY用関数
27.8. 制御関数
27.9. 警告処理
27.10. 環境変数
27.11. パスワードファイル
27.12. スレッド化プログラムの振舞い
27.13. libpqプログラムの構築
27.14. サンプルプログラム

libpq は、C 言語のアプリケーションプログラマ用の PostgreSQL インタフェースです。 libpq は、クライアントプログラムから PostgreSQL のバックエンドサーバに問い合わせを渡し、その結果を受け取るためのライブラリ関数の集合です。 libpq は、libpq++(C++)、libpgtcl(Tcl)、PerlECPG などを含む、PostgreSQL の他のアプリケーションインタフェースを支えるエンジンでもあります。 したがって、libpq の動作は、これらのパッケージを使用する人にとって重要なものになります。

本章の最後に、libpq の使い方を示す、数個の短いプログラム(項27.14)があります。 また、ソースコード配布物内のsrc/test/examplesディレクトリに、libpq を利用したアプリケーションプログラムの完全な例があります。

libpq を使用してフロントエンドプログラムを作成するには、ヘッダファイル libpq-fe.h のインクルードと、libpq ライブラリとのリンクが必要です。

27.1. データベース接続制御関数

PostgreSQL のバックエンドサーバとの接続を作成するには、以下の関数を使用します。 アプリケーションプログラムは、バックエンドとの接続を一度に複数個開くことができます。 (1 つの理由として、複数のデータベースへのアクセスが挙げられます。) 個々の接続は、PQconnectdb または PQsetdbLogin 関数を呼び出すことで得られる PGconn オブジェクトによって表されます。 なお、これらの関数は、PGconn オブジェクトに割り当てるほんのわずかなメモリの余裕さえもない場合を除き、NULL ではなく常にオブジェクトのポインタを返します。 また、この接続オブジェクトを通じて問い合わせを送る前に、PQstatus 関数を呼び出して、データベースとの接続に成功したかどうかをチェックすべきです。

PQconnectdb

新たにデータベースサーバへの接続を作成します。

PGconn *PQconnectdb(const char *conninfo);

この関数は、conninfo 文字列から取得したパラメータを使用して、データベースとの接続を新たに1つ確立します。 後述の PQsetdbLogin とは異なり、関数のプロトタイプを変更せずにパラメータを拡張できますので、アプリケーションプログラムを作成する際には、このルーチン(もしくは非ブロックモードでよく似た処理をする PQconnectStartPQconnectPoll )を使用することをお勧めします。

空の文字列を渡すことで、全てのパラメータはデフォルトを使用できます。 また、空白文字で区切ることで1つ以上のパラメータを設定することができます。 それぞれのパラメータは、keyword = value という形で設定します。 (空の値や空白文字を含む値を書く場合は、単一引用符で囲みます。 例えば、keyword = 'a value' といった具合です。 値中の単一引用符とバックスラッシュは \'\\ というように、バックスラッシュでエスケープしなければなりません。) 等号の前後のスペースは、任意で付けられます。

現時点で有効なパラメータのキーワードは以下に示すとおりです。

host

接続するホスト名を指定します。 この引数をスラッシュで始めた場合、TCP/IP による通信ではなく、Unix ドメインの通信を明示することになります。 その場合、この値はソケットファイルを格納するディレクトリの名前になります。 デフォルトでは、/tmp にある Unix ドメインのソケットに接続します。

hostaddr

接続するホストの IP アドレスを指定します。 これは、172.28.40.9といった標準的なIPv4アドレス書式でなければなりません。 使用するマシンでIPv6をサポートする場合は、そのアドレスを使用することもできます。 このパラメータに非0長の文字列が指定されると、TCP/IP 通信が常に使用されます。

hostの代わりにhostaddrを使用することで、アプリケーションがホスト名の検索をせずに済みます。 特に、時間に制約のあるアプリケーションでは、重要になるでしょう。 しかし、Kerberos 認証を行うアプリケーションでは、ホスト名が必要になります。 結局、以下のようになります。 hostaddr を使わずにhostを指定した場合は、ホスト名の検索が発生します。 hostを使わず、hostaddr を指定した場合、hostaddr はリモートマシンのアドレスとなります。 この時、Kerberos を使用している場合は、IP アドレスからホスト名の逆引きが行われます。 hosthostaddrの両方を指定した場合、hostaddr がリモートマシンのアドレスとなります。 この時、Kerberos が使用されていない場合はhostに与えられた値は無視され、使用されている場合は Kerberos 認証にhostの値が使用されます。 (libpq に渡されたホスト名が、hostaddr に対応するマシンの名前と一致しない場合は、認証に失敗する可能性があるので、注意してください。) また、hostaddrではなくhost$HOME/.pgpassでの接続の識別に使用されます。

ホスト名もホストのアドレスも用いない場合、libpq はローカルの Unix ドメインのソケットを使用して接続します。

port

サーバホストでの接続用のポート番号、または、Unix ドメイン接続の場合は、ソケットファイルの拡張子を指定します。

dbname

データベース名を指定します。 デフォルトはユーザ名と同じです。

user

データベースへ接続するPostgreSQLユーザ名を指定します。

password

サーバがパスワードによる認証を必要とした場合に使用されるパスワードを指定します。

connect_timeout

接続用の最大待機時間を秒単位で指定します。 (10進数整数で表した文字列として記述してください。) ゼロもしくは未設定は、無限時間待機を意味します。 2秒未満の待機時間を使用することは勧めません。

options

サーバに送信するコマンドラインオプションを指定します。

tty

無視されます。 (以前は、これはサーバデバッグ出力を送信する場所を指定するものでした。)

sslmode

このオプションは、 どのSSL接続の優先度でサーバと調停するかを決定します。 4つのモードがあります。 disableは暗号化しないSSL接続のみを試みます。 allowはまず非SSL接続を試み、失敗したらSSL で調停を行ないます。 prefer(デフォルトです)は、まずSSL接続を試み、失敗したら通常の非SSL接続で調停を行ないます。 requireSSL接続でのみ調停を行ないます。

SSLサポートなしでPostgreSQLがコンパイルされた場合に、requireを使用するとエラーになります。 また、allowpreferは使用できますが、libpqSSL接続の調停を行なうことはできません。

requiressl

このオプションは、sslmode 設定により廃れたものになりました。

1に設定することで、サーバへのSSL 接続が必要になります。 (これはsslmoderequireと同じです。) サーバがSSL 接続を受け付けない場合、Libpq は接続を拒絶します。 0(デフォルト)に設定することで、サーバと調停を行います。 (sslmodepreferと同じです。) SSLサポート付きでPostgreSQLをコンパイルした場合にのみ、このオプションが利用できます。

service

他のパラメータ用に使用されるサービス名です。 pg_service.conf内の追加的な接続パラメータを保持するサービス名を指定します。 これによりアプリケーションはサービス名だけを指定でき、接続パラメータを集中的に保守できるようになります。 このファイルの設定方法についての情報はPREFIX/share/pg_service.conf.sampleを参照してください。

パラメータが指定されなかった場合には、対応する環境変数がチェックされます (項27.10 を参照してください)。 環境変数も設定されていない場合は、組み込みのデフォルト値が使用されます。

PQsetdbLogin

新たにデータベースサーバへの接続を作成します。

PGconn *PQsetdbLogin(const char *pghost,
                     const char *pgport,
                     const char *pgoptions,
                     const char *pgtty,
                     const char *dbName,
                     const char *login,
                     const char *pwd);

これはパラメータ群を固定したPQconnectdbプロシージャです。 設定できないパラメータが常に固定値になる点を除き、同一の機能を持ちます。 固定したパラメータに対してNULLもしくは空文字列とすると、それはデフォルトを使用することになります。

PQsetdb

新たにデータベースサーバへの接続を作成します。

PGconn *PQsetdb(char *pghost,
                char *pgport,
                char *pgoptions,
                char *pgtty,
                char *dbName);

これは、loginpwdにヌルポインタを設定するPQsetdbLoginを呼び出すマクロです。 非常に古いプログラムへの後方互換性のために提供されています。

PQconnectStart
PQconnectPoll

ブロックしない方法で、データベースサーバへの接続を作成します。

PGconn *PQconnectStart(const char *conninfo);

PostgresPollingStatusType PQconnectPoll(PGconn *conn);

これら2つの関数を使用して、リモートI/Oの実行時にアプリケーションスレッドの実行がブロックされないように、データベースサーバへの接続を作成します。

PQconnectStart に渡された conninfo 文字列からパラメータを取得し、データベース接続が確立されます。 この文字列は、上述の PQconnectdb の場合と同じ形式で記述されています。

PQconnectStartPQconnectPoll は、以下の制限下ではブロックしません。

  • hostaddrhost パラメータは、ホスト名からの IP アドレス検索やホスト名の逆引きが起こらないように適切に使用されなければいけません。 これらのパラメータについての詳細は、前述の PQconnectdb の節を参照してください。

  • PQtrace を呼び出す場合は、トレースに使用するストリームオブジェクトがブロックされないことが保証されていなくてはなりません。

  • プログラマ自身が、後に示すように、PQconnectPoll を呼び出す前にソケットが適切な状態にあることを保証しなくてはいけません。

非ブロック接続を始めるにはまず、conn=PQconnectStart("connection_info_string") を呼び出します。 conn がヌルである場合、libpq が新たに PGconn 構造体を割り当てられなかったことを表します。 そうでない場合は、適切な PGconn へのポインタが返されます (ただし、データベースに正しく接続されていることを表しているわけではありません)。 PQconnectStart から値が返ってきた段階で、status=PQstatus(conn) を呼び出します。 もし、statusCONNECTION_BAD と等しい場合には、PQconnectStart が失敗しています。

PQconnectStart が成功したら、次は接続シーケンスを進めるために、libpq をポーリングします。 データベース接続の背後にあるソケットの記述子を取り出すには、PQsocket(conn)を使用します。 以下の繰り返しです。 直前のPQconnectPoll(conn)PGRES_POLLING_READINGの場合、ソケットの読み込み準備が整うまで待機します。 (select()poll()などのシステム関数で示されます。) そして、再度PQconnectPoll(conn)を呼び出します。 反対に直前のPQconnectPoll(conn)PGRES_POLLING_WRITINGの場合、ソケットの書き込み準備が整うまで待機し、その後、PQconnectPoll(conn)を再度呼び出します。 まだPQconnectPollを呼び出していない場合、つまり、PQconnectStartの呼び出し直後では、直前がPGRES_POLLING_WRITINGであった場合と同様の処理を行ないます。 この繰り返しをPQconnectPoll(conn)が、接続手続きの失敗を示すPGRES_POLLING_FAILED、もしくは、接続確立に成功したことを示すPGRES_POLLING_OKを返すまで継続します。

接続している間は、いつでも PQstatus を呼び出すことで、接続の状態をチェックすることができます。 この関数がCONNECTION_BAD を返す場合、接続手続きは失敗しており、CONNECTION_OK を返す場合、接続が確立しています。 上述のように、このいずれの状態も、PQconnectPoll の戻り値から同様に検出できます。 これ以外の状態は、非同期の接続手続きの間(のみに)現れることがあります。 これらは、接続プロシージャの現在の段階を示すものであり、例えばユーザへのフィードバックを提供することに使用できます。 以下の状態があります。

CONNECTION_STARTED

接続の確立待ち状態です。

CONNECTION_MADE

接続は OK です。 送信待ち状態です。

CONNECTION_AWAITING_RESPONSE

サーバからの応答待ち状態です。

CONNECTION_AUTH_OK

認証済みです。 バックエンドの起動待ち状態です。

CONNECTION_SSL_STARTUP

SSL暗号化の調停状態です。

CONNECTION_SETENV

環境が提供するパラメータ設定の調停状態です。

これらの定数は(互換性を保つため)なくなることはありませんが、アプリケーションは、これらが特定の順で出現したり、本書に書いてある値のどれかに必ずステータス値が該当するということを決して当てにしてはいけません。 アプリケーションは、以下に示すようにするべきです。

switch(PQstatus(conn))
{
    case CONNECTION_STARTED:
        feedback = "Connecting...";
        break;

    case CONNECTION_MADE:
        feedback = "Connected to server...";
        break;
.
.
.
    default:
        feedback = "Connecting...";
}

PQconnectPollを使用する場合、connect_timeout接続パラメータは無視されます。 経過時間が長過ぎるかどうかの判定はアプリケーションの責任で行ないます。 さもないと、PQconnectStartの後のPQconnectPollの繰り返しがPQconnectdbと同じになります。

PQconnectStart が非ヌルポインタを返した場合、処理を終了する際には、構造体や関連するメモリブロックを始末するために、PQfinish を呼び出さなくてはいけません。 この処理は、接続試行が失敗した場合やその試行を中断する場合にも、必ず実行されなければいけません。

PQconndefaults

デフォルトの接続オプションを返します。

PQconninfoOption *PQconndefaults(void);

typedef struct
{
    char   *keyword;   /* このオプションのキーワード */
    char   *envvar;    /* 代替となる環境変数の名前 */
    char   *compiled;  /* 代替となるコンパイル時に組み込まれたデフォルト値 */
    char   *val;       /* オプションの現在値、もしくは、NULL */
    char   *label;     /* 接続ダイアログ内の当該フィールドのラベル */
    char   *dispchar;  /* 接続ダイアログ内の当該フィールドで表示する文字
                          値:
                          ""        入力された値をそのまま表示
                          "*"       値を隠すパスワードフィールド用
                          "D"       デバッグオプション。デフォルトで何も表示しません */
    int     dispsize;  /* ダイアログ用のフィールドの大きさ(文字数単位) */
} PQconninfoOption;

接続オプションの配列を返します。 これは、使用可能な PQconnectdb 用オプションのすべてや、その時点でのデフォルト値を決定するために使用することができます。 戻り値は、PQconninfoOption構造体の配列へのポインタで、keywordポインタがヌルとなる項目が配列の末尾にきます。 現在のデフォルト値(val フィールド)は、環境変数や他のコンテキストに依存します。 呼び出し側では、接続オプションの情報は、読み込み専用として取り扱わなければいけません。

オプションの配列を処理した後は、PQconninfoFree を使用して解放します。 この処理をしないと、PQconndefaults が呼び出されるたびに少しずつメモリリークが発生します。

PQfinish

サーバとの接続を閉ざします。 また、PGconnオブジェクトが占めるメモリを解放します。

void PQfinish(PGconn *conn);

たとえサーバへの接続試行が失敗したとしても(PQstatus で調べます)、アプリケーションは PQfinish を呼び出し PGconn オブジェクトが占めるメモリを解放するべきです。 そして PQfinish を呼び出したら、もう PGconnへのポインタを使ってはいけません。

PQreset

サーバへの通信チャンネルをリセットします。

void PQreset(PGconn *conn);

この関数はサーバへの接続を閉じ、以前使用したパラメータをすべて使用して、同一のサーバへ新しく接続を確立します。 これは、作業中の接続が失われた場合のエラーの修復に役立つでしょう。

PQresetStart
PQresetPoll

非ブロッキング方式で、サーバへの接続チャンネルをリセットします。

int PQresetStart(PGconn *conn);

PostgresPollingStatusType PQresetPoll(PGconn *conn);

これらの関数はサーバへの接続を閉じ、それから再度、以前使用したパラメータをすべて使用して、同じサーバと新たな接続を確立しようとします。 これらは作業中の接続が失われた場合のエラー修復に役立つでしょう。 PQreset(前述) との違いは、この 2 つの関数が非ブロック方式で動作することです。 また、これらの関数はPQconnectStartPQconnectPoll と同じ制限を受けます。

接続リセットを始めるには、PQresetStartを呼び出します。 この関数が0を返す場合、リセットに失敗しています。 戻り値が 1 ならば、PQconnectPoll を使って接続を確立した時と同じように、PQresetPoll を使用してリセットのポーリングを行ないます。