libpgtclを使ってみよう
 ここからが本題の libpgtcl を使ったサンプルです。

#! /usr/local/bin/tclsh
set env(PGCLIENTENCODING) UNICODE

if {$argc >= 1} {
    set name [lindex $argv 0]
} else {
    puts "usage:$argv0 name"; exit
}
load /usr/local/pgsql/lib/libpgtcl.so

#set DBHOST localhost
set DBNAME "testdb"
#set con [pg_connect $DBNAME -host $DBHOST]
set con [pg_connect $DBNAME]

set q "select * from country where name = '$name'"
set result [pg_exec $con $q]
set rows [pg_result $result -numTuples]
if {$rows == 0} {
    puts [pg_result $result -error]
} else {
    for {set i 0} {$i<$rows} {incr i} {
        puts [pg_result $result -getTuple $i]
    }
}
pg_disconnect $con
# end.

  1. 順を追って説明してみます。 まず環境変数の設定として、Tcl 8.1以降では PGCLIENTENCODINGUNICODEを設定しておきます。
    set env(PGCLIENTENCODING) UNICODE
    
    こうすると、Tcl世界のUTF-8で書かれたSQL文等の命令文字列が PostgreSQLの内部文字コード(EUC_JPなど)に自動変換され、 処理された結果が再びUTF-8に自動変換されて返ってくるようになります。
  2. libpgtclのロードはこのようにloadコマンドで行ってもよいですし
    load /usr/local/pgsql/lib/libpgtcl.so
    pkgIndex.tclを作ってパッケージを整備しているなら、 「package require pgtcl」でもうまくいくかもしれません。 これで、「pg」で始まるいくつかのTclコマンドが処理系に追加されます。
  3. PostgreSQLデータベースに接続するには、pg_connect コマンドを使います。 PostgreSQLのpostmasterが自分のマシンで動いている場合には、 「createdb」ツールで作成したデータベース名を指定します。
    set con [pg_connect $DBNAME]
    戻り値は接続(connection)を一意識別するためのもので、 openコマンドが返すファイルハンドルと同じようなものです。 ネットワークを介して他のマシンのpostmasterに接続するには、
    set con [pg_connect $DBNAME -host $DBHOST]
    このようにpostmasterが動いているマシンの名前を指定します。
  4. 接続できたら、任意のSQL文をpg_exec コマンドで実行させることができます。
    set result [pg_exec $con $sql_statement]
    この戻り値は、結果を保持した文字列そのものではありません。 従って、これをそのまま表示したりしても意味がありません。
  5. 結果が何行あるかは、pg_exec コマンドの戻り値を pg_result コマンドに渡すことで取得できます。
    set rows [pg_result $result -numTuples]
  6. 結果が何行あるかが得られました。今度は、同じように pg_result コマンドを使ってそれぞれの行の内容を取得できます。
    for {set i 0} {$i<$rows} {incr i} {
        set row [pg_result $result -getTuple $i]
    #    puts $row
        puts [encoding convertfrom euc-jp $row]
    }
    
  7. 結果がエラーかどうかは、 pg_resultコマンドの-statusを使って知ることができます。 SQL文に構文エラーがあるときなどは、
    pg_result $result -status
    
    の値が「PGRES_FATAL_ERROR」などの文字列になるので、それを検出したら pg_result コマンドの -error を使ってエラー内容を取得してエラー処理をします。
    pg_result $result -error
    
  8. 結果がもういらなくなったら、次のようにしてバッファ領域をクリアしておきます。 これをしないとSQL文を実行するたびに結果がどんどん溜っていくので、 繰り返しpg_execを行っていると、そのうちにエラーを起こしてしまいます。
    pg_result $result -clear
  9. 思う存分SQL文を実行したら、最後に pg_disconnectコマンドで接続を切って処理は完了です。
    pg_disconnect $con

 ユーザー定義関数をlibpgtclから使う方法も、 結局上のSELECT文ということになるのですが、 それでは紹介が終わってしまうので、一応サンプルも載せておきます。 せっかく書いたんだから、ネッネッ(おしきせがましく)


set env(PGCLIENTENCODING) UNICODE
load /usr/local/pgsql/lib/libpgtcl.so Pgtcl
set con [pg_connect udb]

set date "2001-09-02"
set s "SELECT COUNT_REQ_BY_CDATE('$date')"

set result [pg_exec $con $s]
if {"[pg_result $result -status]" == "PGRES_FATAL_ERROR"} {
    puts [pg_result $result -error]
    exit 0
}
set num [pg_result $result -numTuples]
puts "all: $num rows."

for {set i 0} {$i<$num} {incr i} {
    set s [pg_result $result -getTuple $i]
    puts "結果: $s"
}
pg_result $result -clear
pg_disconnect $con
# end.

むー。せっかく書いたとはいえ、何も言うことがないですね… 元々libpgtclの標準の書き方とゆーものを知って書いているわけでもないので、 サンプルと言えるかどうかは定かではないです。まま、 これでユーザー定義関数も普通に使えるということで、 お茶を濁してしまいましょう。

 というわけで、かけ足でlibpgtclの紹介をしてみました。 PostgreSQLはフリーであるという利点が逆に誰もサポートしてくれないという点で企業ユースではリスクになると思われがちですが、 十分に強力で、安定していて、操作しやすいRDBMSとして、 もっと認知されてもよい完成度を既にもっています。 最大の欠点はグラフィカルな画面操作を行うツールがないことですが、 Tcl/Tkはこれを補うのにぴったりの言語です。


BLTも使うとみためもよいです
 Tcl/Tkの最も有名な拡張ライブラリのひとつBLTのバージョン2.4o以降では、 ハイアラキカルテーブル(hiertable)というTkウィジェットが使えます。 これは見ての通りのこんな感じのウィジェットで、 QtやGtk+にもある高度なウィジェットです。

このhiertableのように縦横のシート状にデータを配置することができるウィジェットが今まで標準Tkにはなかったので、 すっきりしたデータ表示画面が作れなかったのですが、 このウィジェットはまさに救世主です。

先述の通り、 PostgreSQLを使ったシステムはWebブラウザでPHPなどを使って接続する検索系がほとんどですが、 Tcl/Tkを使うと簡単なクライアント・サーバー型の検索・更新系のツールが作れます。

拡張レビュー分室 top
(first uploaded 2001/09/02 last updated (not ever) , MISUMI URANO )