プログラミングインターフェース

「第9章データ型」「第10章トランザクションとロック」 「第11章性能」「第13章テーブル管理」などには、 PostgreSQLのみならず、データベースシステムを使いこなしていくうえで 重要な概念が含まれています。

データベースサーバと問い合わせクライアント

現在、実習で使っている、サーバ/クライアントの構成。
(fms-168)
   postmaster (DBサーバプロセス) ←→ データベース
  ↑tcp/5432
  ↓  SQLによる問い合わせ
(sws01..60)
   psql (ユーザインターフェース)
この下の部分を取り替えると、別のユーザインターフェースが 使える。

例:pgaccess ... Tcl/Tk を用いた GUI インターフェース

さらに、ユーザ(あるいはソフトウェアメーカ)が独自にインターフェース を開発することも可能である。そのような、プログラミングのための インターフェース(ライブラリ)がいくつか存在する。
(API ... Application Programming Interface と呼ぶこともある)

C言語インターフェース(LIBPGEASY)

state.c
/*
 * libpgeasy example
 */

#include <stdio.h>
#include <libpq-fe.h>
#include <libpgeasy.h>

int main() {
    char state_code[3];         /* ユーザ入力・州 */
    char query_string[256];     /* 生成されたSQLを保持 */
    char state_name[31];        /* 返された州コードを保持 */

    connectdb("dbname=test host=fms-168"); /* データベース接続 */
    printf("州コードを入力してください: ");
    scanf("%2s",state_code);
    sprintf(query_string,       /* SQL文の生成 */
        "SELECT name FROM statename WHERE code = '%s'",
        state_code);
    doquery(query_string);      /* 問い合わせ実行 */
    while (fetch(state_name) != END_OF_TUPLES)  /* 全ての列について */
        printf("%s\n", state_name);             /* 値を表示 */
    disconnectdb();             /* データベース切断 */
    return 0;
}

コンパイル

コンパイルには gcc を使う。(F社製コンパイラもあるが、gcc のほうがよい) 実行ファイルを a.out でない名前にしたい場合には、-oオプション を指定する。
tkikuchi@fms% ls
state.c
tkikuchi@fms% gcc -o state state.c
state.c:6: libpq-fe.h: ファイルもディレクトリもありません。
state.c:7: libpgeasy.h: ファイルもディレクトリもありません。
ここで、エラーが出るのは、ソースの中で指定されているヘッダファイル (libpq-fe.h libpgeasey.h)がシステム標準のヘッダファイルディレクトリ (/usr/include) に入っていないためである。ヘッダファイルディレクトリ の追加を指示する -I オプションを使う。上記のヘッダファイルは、 現在のシステムの場合 /pub/sol8/pgsql/include に入っている。 (このディレクトリは postgresql のインストール時にシステム管理者が 決める).
tkikuchi@fms% gcc -o state state.c -I/pub/sol8/pgsql/include
未定義の                        最初に参照している
シンボル                            ファイル
connectdb                           /var/tmp/cc5BT8ch.o
doquery                             /var/tmp/cc5BT8ch.o
fetch                               /var/tmp/cc5BT8ch.o
disconnectdb                        /var/tmp/cc5BT8ch.o
ld: 重大なエラー: シンボル参照エラー。state に書き込まれる出力はありません。
collect2: ld returned 1 exit status
このエラーはコンパイルの最終段階で実行ファイルを生成する際に、 未定義のシンボルがあると言っている。このシンボルはpgeasyライブラリに 入っている関数である。これも、システム標準ライブラリには無いので、 -L オプションで/pub/sol8/pgsql/libにあることを教えてあげなければ ならない。(下の例では直前のコマンドを示す !!を用いているが 最初からエラー無しでコンパイルしたければ、2行目に生成されたコマンドを 手で入れる)
tkikuchi@fms% !! -L/pub/sol8/pgsql/lib -lpgeasy
gcc -o state state.c -I/pub/sol8/pgsql/include -L/pub/sol8/pgsql/lib -lpgeasy
一応、コンパイルに成功した。./state で実行してみる。
tkikuchi@fms% ./state
ld.so.1: ./state: 重大なエラー: libpgeasy.so.2: open に失敗しました: ファイルも?
ィレクトリもありません。
強制終了
ところが、実行時にエラーになる。これは、pgeasy ライブラリが、 「共有ライブラリ」として作成されているためで、実行時にロードされる ライブラリが標準のライブラリでは無いため、そのありか(ディレクトリ) を何らかの方法で設定しておく必要がある。これには2つの方法があり、 古典的な方法ではコマンドを実行するユーザが LD_LIBRARY_PATH 環境変数 に設定するというものだが、ここでは、新しい方法でコンパイル時に 設定する方法を使う。コンパイルの時に -R オプションでライブラリを 探すディレクトリを指定する。(history機能を使って2つ前のコマンドに オプションを追加している)
tkikuchi@fms% !-2 -R/pub/sol8/pgsql/lib
gcc -o state state.c -I/pub/sol8/pgsql/include -L/pub/sol8/pgsql/lib -lpgeasy -R/pub/sol8/pgsql/lib

実行

正常にコンパイルできれば、以下のようにプロンプトに対して2文字の 州コードを入力すると答えが出てくる。
tkikuchi@fms% ./state
州コードを入力してください: AL
Alabama

Python (スクリプト言語)

state.py
#!/bin/env python
#
# Python example
#
from pg import DB

conn = DB('test','fms-168')

state_code = raw_input('州コードを入力してください:  ')

for name in conn.query(
        "SELECT name FROM statename WHERE code = '%s'" % state_code
        ).getresult():
    print "%s" % name

Pythonスクリプトの実行

スクリプト言語ではライブラリの結合の部分はあらかじめ 解決されているので、そのまま実行できる。 (自分でPythonとそのライブラリをインストールする場合には、 Cライブラリの所在を考慮しなければならないことがある)
  1. python インタラクティブモードで実行
    tkikuchi@fms% python
    Python 2.2.1 (#3, May 22 2002, 15:29:49)
    [GCC 2.95.3 20010315 (release)] on sunos5
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import state
    州コードを入力してください:  AL
    Alabama
    >>>
    
  2. pythonコマンドでスクリプトを指定
    tkikuchi@fms% python state.py
    州コードを入力してください:  AK
    Alaska
    
  3. スクリプトに実行パーミッションを与えておき、スクリプト名だけで実行
    tkikuchi@fms% chmod +x state.py
    tkikuchi@fms% ./state.py
    州コードを入力してください:  AZ
    Arizona
    

CGIインターフェース

CGIインターフェースはWebブラウザとのやりとりをPostgreSQLに 中継するために使うことができる。ここでは、Pythonを使った CGIスクリプトを取り上げる。
state.cgi
#!/pub/sol8/bin/python

from pg import DB
import cgi

print "Content-Type: text/html; charset=EUC-JP"
print ""

def prompt():
    print """<html>
        <head><title>アメリカの州コード</title></head>
        <body>
        <h1>アメリカの州コード</h1>
        州コードを入力してください
        <p>
        <form method="post" action="state.cgi">
        <input type="text" name="statecode">
        <input type="submit" name="submit" value="送信">
        </form>
        </body>
        </html>"""

def answer(statecode):
    db = DB('test','fms-168')
    print "<html><body>"

    r = db.query("""SELECT name
                FROM statename
                WHERE code = '%s' ;""" % statecode
        ).getresult()

    print "<h3>%s</h3>" % statecode
    for x in r:
        print '%s<br>' % x
    print "</body></html>"

form = cgi.FieldStorage()

if form.has_key('statecode'):
    statecode = form['statecode'].value
    answer(statecode)
else:
    prompt()
このプログラムを実行するには、Webサーバが必要である。一般にはWebサーバの 立ち上げには root 権限が必要であるが、ここでは特権ポートを使わずに 一般ユーザ権限で立ち上げてみる。Webサーバのプログラムとしては Apache httpd 1.3.31 を使う。
以下の作業に入る前に path に /usr/ccs/bin が入っていることを 確認する。無ければ set path = ($path /usr/ccs/bin) を実行。 (または .cshrc を編集してから csh を立ち上げる)
tkikuchi@fms% cd
tkikuchi@fms% mkdir -p apache/src
tkikuchi@fms% cd apache/src
tkikuchi@fms% cp ~tkikuchi/src/apache_1.3.31.tar.gz .
tkikuchi@fms% gzcat apache_1.3.31.tar.gz | tar xvf -
....
tkikuchi@fms% cd apache_1.3.31
tkikuchi@fms% ./configure --prefix=/home/<ユーザID>/apache --runtimedir=/tmp
....
tkikuchi@fms% make
....
tkikuchi@fms% make install
....
+--------------------------------------------------------+
| You now have successfully built and installed the      |
| Apache 1.3 HTTP server. To verify that Apache actually |
| works correctly you now should first check the         |
| (initially created or preserved) configuration files   |
|                                                        |
|   /home/tkikuchi/apache/conf/httpd.conf
|                                                        |
| and then you should be able to immediately fire up     |
| Apache the first time by running:                      |
|                                                        |
|   /home/tkikuchi/apache/bin/apachectl start
|                                                        |
| Thanks for using Apache.       The Apache Group        |
|                                http://www.apache.org/  |
+--------------------------------------------------------+
tkikuchi@fms%
以上の様なメッセージが出ればインストール成功である。 エラーがあったときは、エラーメッセージをよく読んで対処する。

Apache httpd の起動

tkikuchi@tws% ~/apache/bin/apachectl start
[Sun Jul  7 13:43:08 2002] [alert] httpd: Could not determine the server's fully
 qualified domain name, using 133.97.168.100 for ServerName
/home/tkikuchi/apache/bin/apachectl start: httpd started
起動に成功すると、上のようなメッセージが表示される。また、以下のように ps コマンドで確認することもできる。ブラウザでアクセスするには、 http://localhost:8080/を開く。 うまく表示できない場合は、Proxyの設定が「直接接続」になっていることを確認する。 (編集->設定->詳細->プロキシで設定)
tkikuchi@tws% ps -ef | grep tkikuchi
     UID   PID  PPID  C    STIME TTY      TIME CMD
tkikuchi  8300  8299  0 13:43:08 ?        0:00 /home/tkikuchi/apache/bin/httpd
tkikuchi  7758  7757  0 13:37:32 pts/2    0:00 -csh
tkikuchi  8299     1  0 13:43:08 ?        0:00 /home/tkikuchi/apache/bin/httpd

Cgiスクリプトの設定

state.cgi スクリプトは ~/apache/cgi-bin に格納する。 実行権限を確認し、ブラウザで http://localhost:8080/cgi-bin/state.cgiを開く。
tkikuchi@tws% cd ~/apache/cgi-bin
tkikuchi@tws% ls -l
合計 10
-rw-r--r--   1 tkikuchi isstaff      273  7月  7日  10:20 printenv
-rwxr-xr-x   1 tkikuchi isstaff      850  7月  7日  10:40 state.cgi
-rw-r--r--   1 tkikuchi isstaff      757  7月  7日  10:20 test-cgi

Httpd の停止

httpd の停止は以下のようにする。
tkikuchi@tws% ~/apache/bin/apachectl stop
/home/tkikuchi/apache/bin/apachectl stop: httpd stopped
* ブラウザのProxy設定を変更した場合、元に戻しておかないと、学外へ接続できなくなります

Web連携データベースのモデル

(fms-168)
   postmaster (DBサーバプロセス) ←→ データベース
  ↑tcp/5432
  ↓  SQLによる問い合わせ
(sws01..60)
   Apache httpd + Python CGI+PyGreSQL(pg モジュール)
  ↑tcp/8080 (一般には80)
  ↓  HTTPプロトコル
(一般ユーザ)
   ブラウザ (ユーザインターフェース)