要約:データベース接続用のパッケージを追加するだけ。Windows用ポータブル版には初めからパッケージが同梱されてました。接続後は普通にSQL文でデータを取得できます。
Contents


実行環境
Windows7 32bit + GNU Octave 4.0(ポータブル版)+ PostgreSQL Portable 9.4.1

GNU Octaveの準備は
昨日と同様、こちらにあるoctave-4.0.0_0.zipをダウンロードし、好きな場所に解凍するだけ。中のbinフォルダ ↓ に各種プログラムがあり、ここをカレントとしてコンソールを起動し、CUIoctave-cliを立ち上げて作業します。冒頭の画像のGUIは、準備したけど結局使いませんでした(後述)。

> octave-cli


上が起動時の画面で、Rと同様にメッセージが結構長い。-hを付けて実行すると起動時のコマンドラインオプション一覧が示され ↓-qなどでメッセージ非表示になると分かったので、次からそうします。コンソールのクリアはCtrl
+L(これもRと同様)。終了はexit, quitどちらも可。
> octave-cli -h


パッケージ追加とPostgreSQLへの接続
GNU Octaveのパッケージ操作は、公式マニュアル(英語)の第38にあります。基本はpkg○○○○というコマンドを打つこと。pkg listでインストール済みパッケージ一覧ですが ↓ ポータプル版の初期状態では何も入ってなかった。
> octave-cli -q
octave:■> pkg list  % ■は実際は行番号。以下同様
no packages installed.


解凍したうちsrcフォルダ下に各種パッケージがあり、database-2.3.2.tar.gzを発見。これを入れます。
octave-4.0.0_0
┣ bin ┗ src
┗ database-2.3.2.tar.gz


pkg installに続けてパッケージを指定してインストール。octave-cliを起動したbinフォルダからの相対パスで大丈夫でした。初めてのパッケージインストールなので新規フォルダ作成があり、そのメッセージ(警告)とかが出ますが、ひとまず成功。続いてpkg loadコマンドで使う準備をします。
%パッケージインストール.フォルダ作成の警告とか出る
octave:■> pkg install ../src/database-2.3.2.tar.gz

%パッケージロード.成功したらメッセージ特になし
octave:■> pkg load database


早速データベースパッケージのコマンドでPostgreSQLに接続してみます。接続文字列を、setdboptsという関数で「"host", "ホスト名", "dbname", "データベース名",…」のように指定して作成。これをpq_connect関数に渡し、戻り値を適当な変数に入れます。下のようにポート番号を省略したら、デフォルトの5432で稼動してるサーバに接続できたので、他の項目もデフォルト値があるかも。
%データベースに接続.成功したらメッセージ特になし
octave:■> conn = pq_connect(setdbopts(
    "host", "localhost",
    "dbname", "postgres",
    "user", "postgres",
    "password", "****"));


Octave(とMATLAB)は、コマンド末尾にセミコロンを付けると実行結果を表示せず、セミコロンがないと結果を表示するという独特の動作をします。上の「データベース接続と変数への格納」を末尾セミコロンなしで実行したら ↓ エラーが出ましたが、これは表示に関するもので(PGconn型をprint文に渡せない)DB接続と変数への格納は成功してます。ちょっと分かりにくい。


接続を閉じるのはpq_closeコマンドで、先ほど接続を格納した変数を渡すだけ。
octave:■> pq_close (conn);


簡単なクエリ
pq_exec_paramという関数を使い、第一引数に先ほど確立した接続の変数を、第二引数にSQL文字列を入れると普通にPostgreSQLにクエリでき、戻り値がOctaveのネイティブデータになるようです。接続できてない場合は ↓ こんなエラーが発生。
octave:■> dat = pq_exec_params(conn,
>     "SELECT * FROM pg_tables LIMIT 10;");
error: __pq_exec_params__: connection not open
error: called from
    pq_exec_params at line 279 column 11


試しにSELECT 1と打ったら、表示内容がとても多くてびっくり。戻り値を入れる変数を指定しない場合、自動的にansという変数に格納されます。これはOctave(とMATLAB)の既定の動作。
octave:■> pq_exec_params(conn, "SELECT 1")
ans =

  scalar structure containing the fields:

    data =
    {
      [1,1] = 1
    }
    columns =
    {
      [1,1] = ?column?
    }
    types =

      scalar structure containing the fields:

        name = pg_catalog.int4
        is_array = 0
        is_composite = 0
        is_enum = 0
        elements = [](0x0)


現在時刻をnow()で表示しようとしたら、更に意表を付いて何か大きな数値、でもUNIXタイムスタンプではなさそう。調べると、databaseパッケージ中にtimeformats.txtという説明文書があり、200011日からの経過ミリ秒と書いてありました。
octave:■> pq_exec_params(conn, "SELECT now()")
ans =

  scalar structure containing the fields:

    data =
    {
      [1,1] = 490808882284000
    }
    columns =
    {
      [1,1] = now
    }
    types =

      scalar structure containing the fields:

        name = pg_catalog.timestamptz
        is_array = 0
        is_composite = 0
        is_enum = 0
        elements = [](0x0)


コンソールの文字列はShift JISで、それに合わせてclient_encodingを指定すれば、日本語で返ってくるクエリ結果もきちんと表示されました。下は、曜日名をローカライズされた名称で得る例。
octave:■> pq_exec_params(conn, "SET client_encoding TO 'SJIS'");
octave:■> pq_exec_params(conn, "SET lc_time TO 'Japanese'");
octave:■> pq_exec_params(conn, "SELECT to_char(now(), 'TMDay')")
ans =

  scalar structure containing the fields:

    data =
    {
      [1,1] = 水曜日
    }
    columns =
    {
      [1,1] = to_char
    }
    types =

      scalar structure containing the fields:

        name = pg_catalog.text
        is_array = 0
        is_composite = 0
        is_enum = 0
        elements = [](0x0)


テーブル形式に表示する方法が、まだ分からない
テーブルがどんな風に表示されるか試したら、[行番号,列番号] =データ本体、という形式でずらずらっと表示され、その後に列名や型が出ました。ページャで1画面ずつめくれるけど、ちょっと微妙。もしかしてテーブル形式で表示する方法があるかも。というか無かったら困るなぁ…。
octave: > dat = pq_exec_params(conn,
    "SELECT * FROM pg_tables LIMIT 10;");
    
% 変数に入れる文で最後にセミコロン付けると結果表示せず、付けないと表示
octave: > dat
dat =

  scalar structure containing the fields:

    data =
    {
      [1,1] = pg_catalog
      [2,1] = pg_catalog
      [3,1] = pg_catalog
      [4,1] = pg_catalog
      [5,1] = pg_catalog
      [6,1] = pg_catalog
      [7,1] = pg_catalog
      [8,1] = pg_catalog
      [9,1] = pg_catalog
      [10,1] = pg_catalog
      [1,2] = pg_statistic
      [2,2] = pg_type
      [3,2] = pg_authid
      [4,2] = pg_user_mapping
      [5,2] = pg_attribute
      [6,2] = pg_proc
      [7,2] = pg_attrdef
      [8,2] = pg_constraint
      [9,2] = pg_index
      [10,2] = pg_operator
      [1,3] = postgres
(以下略)


ページャの動作もよく分からない所があり、常にコンソール下端までいっぱいに表示されるかというとそうでもなく、下のように途中で次頁に送られたりしました。


複文のSQLは実行できない(Rでは可能)ほか注意点
先ほど、SET文を2回発行してクライアント側の文字コードなどを設定した後にSELECT文でクエリする例を書きましたが、これをセミコロンでつないで一つのSQLにすると(いわゆる複文)実行できませんでした。おそらく使ってるlibpqライブラリの関数が、複文を許可しないPQexecParamsのため。下のようにSELECT文を連続させても同じエラーになります。libpqドキュメントの該当箇所はこちら。
octave: > pq_exec_params(conn, "SELECT 1; SELECT 2")
error: __pq_exec_params__: fatal error: ERROR:  cannot
insert multiple commands into a prepared statement

error: called from
    pq_exec_params at line 279 column 11


複文SQLでなくとも、セミコロンで改行した時点でOctaveが「コマンドの終わり」と解釈して実行します。だからセミコロンを含む複数行の文字列は扱えません。何かエスケープする方法があるかもしれないけど。
octave: > pq_exec_params(conn, "SELECT 1;
error: unterminated character string constant
parse error:

  syntax error

>>> pq_exec_params(conn, "SELECT 1;
                                   ^


ちなみにRで、RPostgreSQLパッケージを使うと ↓ こんな風に複文を渡せます。またSQL文字列の途中で改行やセミコロンを挟むことも可能。
> library(RPostgreSQL)
> con = dbConnect(PostgreSQL(), host='localhost', ...)
> dbGetQuery(con, 'SELECT 1; SELECT 2; SELECT 3')
  ?column?
1        3
> 
> dbGetQuery(con, 'SELECT 1;
+     SELECT 2;
+     SELECT 3;
+ ')
  ?column?
1        3

あと、データベースパッケージと関係なくGNU Octaveのコンソール全般について、自分の環境では日本語など非ASCIIを入力できませんでした(入力orペーストした瞬間に消える)。


SourceForge.netが落ちててOctave-Forgeが見れない
このデータベースを含むOctaveの各種パッケージはOctave-Forgeに集まってます。で、これをホスティングしているSourceForge.netが先週からダウンしたため、先週から、今も(722日)見れません。データベースパッケージの詳細や各関数についてリンクを張っておきたかったですが、サイトがずっとこの状態で ↓ 今回はリンク先を確認できず、割愛。


使わなかったけどOctaveGUIの紹介
Octave 4.0からGUIが標準になり、ポータブル版でも同様でした。解凍後の一番上のフォルダにバッチファイルがあり ↓ これでGUIが起動。自分はコンソールに慣れてるのと、これのポータビリティが今いち(GUIの設定ファイルの一部が常にシステムドライブに保存される)なので余り使わなそうですが、一応セットアップした経過をメモしておきます。

初めてGUIを実行すると ↓ こんな画面で設定ファイルの作成が始まり、C:/Users/ユーザ名/.config/octave/qt-settingsに保存されます。後でファイルの場所を変更できるかと思いましたが、できなさそう。最後の画面「エンジョイ!」がこの種の堅いソフトでは意外で、つい笑ってしまった。


↓ 最初の起動時。各ペインはQtQDockWindowと思われ、個別に切り離し・ドッキングできます。コマンドやエディタ等はタブ化も可能。エディタを出すと、その中にメニューバー・ツールバーが出て(二つ目の画像)余り見ない形だけど、こういうインターフェイスもありかな。


↓ 編集メニューから設定変更でき、いろいろ項目がありましたが最初にシステムドライブに作成した設定ファイルは動かせない模様。このへんで、GUIは後日にしてコンソールへ戻りました。