Linux上のPHPからAccessのMDBを使うには
題名の件ですが調査を依頼されたのですが個人的に結構苦戦した部類だったのでメモしておきます。先日書いていたPHPのコンパイルでおかしくなったのはこれをやろうとしてはまりました。
まずはLinuxからMDBを操作できるのか?
ググってみたところでは Microsoft のAccessDB(MDB)をLinuxから使おうと思ったらなかなか手段がないらしく、LinuxのODBC経由で取れるらしいことが判明。ODBC経由でmdbにアクセスするには、MDB Toolsってのと brodbc(ODBC-ODBC Bridge)が使えるらしい。
MDB Tools
MDB Toolsは直接Linux側にmdbを置いて操作できそう!だったので、DLしてコンパイルして試してみた*1けどうまく動かない。どうもまだ開発中(ていうかストップしてる?)らしく、unixODBCのisqlコマンドでSQLを実行するとなぜかループ。当然日本語とかも全く未対応で使えないため使えないと判断。
brodbc (ODBC-ODBC bridge)
これは、開発止まっているようだけど日本で作成されたソフトで、ODBCをネットワーク経由して別のマシンからアクセスできるようにするODBCドライバ。本家見てみるとわかるけど、mdbはLinux単体で直接扱えず、Windowsマシンが必要。
具体的には
- Windows側でコンパネ→ODBCマネージャから読み込ませたいMDBを指定する
- Windows側でbrodbcサーバを起動させ常駐させる(TCP22002番を使う)
- Linux側からbrodbcクライアントODBCドライバからWindowsのbrodbcにへアクセス
- Linux側からSQL実行
てな流れになる。
brodbcのコンパイル
開発が止まっているため、makeするのはなかうまくいかないです。こちらの場合は、unixODBCかiODBCおよび、libiconvの開発ライブラリが必要でした。あらかじめ、パッケージインストールかソースからをmakeしてインストールしておいてください。私の場合はlibiconvとiODBCをソースからインストールしましたのでライブラリは/usr/local配下にインストールされます。手順は省略します。そのあとで、brodbcのmake を行います。
1.ダウンロード・展開
wget http://www.amy.hi-ho.ne.jp/jbaba/brodbc/brodbc03.tgz
tar xfz brodbc03.tgz
cd brodbc03
2. ここで、client/makefile.uxを次のように修正
CC = gcc -c -DUNIX -DICONV
↓
CC = gcc -fPIC -c -DUNIX -DICONV〜中略〜
ODBCLIB = /usr/local/lib/libodbc.so
↓
ODBCLIB = /usr/local/lib/libiodbcinst.so /usr/local/lib/libiconv.so
# ※iodbcとiconvを手動インストールしている場合です。unixodbcだとlibodbcinst.soとなります。
3.common/makefile.ux
CC = gcc -c -DUNIX
↓
CC = gcc -fPIC -c -DUNIX
4.client/brodbc.c を書き換える
30c30 < SQLSMALLINT FAR *pcbConnStrOut, --- > SQLSMALLINT *pcbConnStrOut, 236c236 < SQLSMALLINT FAR *pcbConnStrOut, --- > SQLSMALLINT *pcbConnStrOut, 252c252 < SQLSMALLINT FAR *pcbConnStrOut) --- > SQLSMALLINT *pcbConnStrOut) 282,285c282,285 < SQLSMALLINT FAR *pfSqlType, < SQLUINTEGER FAR *pcbParamDef, < SQLSMALLINT FAR *pibScale, < SQLSMALLINT FAR *pfNullable) --- > SQLSMALLINT *pfSqlType, > SQLULEN *pcbParamDef, > SQLSMALLINT *pibScale, > SQLSMALLINT *pfNullable) 311,312c311,312 < SQLINTEGER irow, < SQLUINTEGER FAR *pcrow, --- > SQLLEN irow, > SQLULEN *pcrow, 365c365 < SQLCHAR FAR *szSqlStrIn, --- > SQLCHAR *szSqlStrIn, 367c367 < SQLCHAR FAR *szSqlStr, --- > SQLCHAR *szSqlStr, 369c369 < SQLINTEGER FAR *pcbSqlStr) --- > SQLINTEGER *pcbSqlStr) 377c377 < SQLSMALLINT FAR *pcpar) --- > SQLSMALLINT *pcpar) 392,393c392,393 < SQLUINTEGER crow, < SQLUINTEGER FAR *pirow) --- > SQLULEN crow, > SQLULEN *pirow) 504c504 < SQLSMALLINT FAR *pcbDriverDesc, --- > SQLSMALLINT *pcbDriverDesc, 507c507 < SQLSMALLINT FAR *pcbDrvrAttr) --- > SQLSMALLINT *pcbDrvrAttr) 519c519 < SQLUINTEGER cbColDef, --- > SQLULEN cbColDef, 522,523c522,523 < SQLINTEGER cbValueMax, < SQLINTEGER FAR *pcbValue) --- > SQLLEN cbValueMax, > SQLLEN *pcbValue) 705,706c705,706 < SQLINTEGER cbValueMax, < SQLINTEGER FAR *pcbValue) --- > SQLLEN cbValueMax, > SQLLEN FAR *pcbValue) 783,784c783,784 < SQLSMALLINT FAR *pcbDesc, < SQLINTEGER FAR *pfDesc) --- > SQLSMALLINT *pcbDesc, > SQLLEN FAR *pfDesc) 1011,1015c1011,1015 < SQLSMALLINT FAR *pcbColName, < SQLSMALLINT FAR *pfSqlType, < SQLUINTEGER FAR *pcbColDef, < SQLSMALLINT FAR *pibScale, < SQLSMALLINT FAR *pfNullable) --- > SQLSMALLINT *pcbColName, > SQLSMALLINT *pfSqlType, > SQLULEN *pcbColDef, > SQLSMALLINT *pibScale, > SQLSMALLINT *pfNullable) 1104,1106c1104,1106 < SQLCHAR FAR *szSqlState, < SQLINTEGER FAR *pfNativeError, < SQLCHAR FAR *szErrorMsg, --- > SQLCHAR *szSqlState, > SQLINTEGER *pfNativeError, > SQLCHAR *szErrorMsg, 1108c1108 < SQLSMALLINT FAR *pcbErrorMsg) --- > SQLSMALLINT *pcbErrorMsg) 1178c1178 < SQLCHAR FAR *szSqlStr, --- > SQLCHAR *szSqlStr, 1468c1468 < SQLSMALLINT FAR *pcbCursor) --- > SQLSMALLINT *pcbCursor) 1482c1482 < SQLSMALLINT FAR *pccol) --- > SQLSMALLINT *pccol) 1518c1518 < SQLCHAR FAR *szSqlStr, --- > SQLCHAR *szSqlStr, 1555c1555 < SQLINTEGER FAR *pcrow) --- > SQLLEN FAR *pcrow) 1626c1626 < SQLUINTEGER cbParamDef, --- > SQLULEN cbParamDef, 1629c1629 < SQLINTEGER FAR *pcbValue) --- > SQLLEN *pcbValue) 1731,1732c1731,1732 < SQLINTEGER cbValueMax, < SQLINTEGER FAR *pcbValue) --- > SQLLEN cbValueMax, > SQLLEN FAR *pcbValue) 1802c1802 < SQLSMALLINT FAR *pcbInfoValue) --- > SQLSMALLINT *pcbInfoValue) 1903c1903 < SQLINTEGER cbValue) --- > SQLLEN cbValue) 1944c1944 < SQLUINTEGER vParam) --- > SQLULEN vParam) 1974c1974 < SQLUINTEGER vParam) --- > SQLULEN vParam) 2127c2127 < SQLSMALLINT FAR *pcbDSN, --- > SQLSMALLINT *pcbDSN, 2130c2130 < SQLSMALLINT FAR *pcbDescription) --- > SQLSMALLINT *pcbDescription)
書き換えないとmake に失敗します。
5.client/iconv.c も書き換えます
36c36 < int in_bytes, out_bytes; --- > size_t in_bytes, out_bytes;
書き換えないとmake に失敗します。
6.make インストール
make
make install
unixODBC または iODBCの設定
/etc/odbcinst.iniの設定
例)
[brodbc03]
Description = ODBC-ODBC bridge
Driver = /usr/local/lib/brodbc.so
FileUsage = 1
#UsageCount = 1
/etc/odbc.ini ファイルにbrodbcを使用できるように記述
例)
[test] # ← Linux odbcでのDSN(DB名)
Driver = brodbc03
Server = windows側のIP
Port = 22002
DSN = test
Database = test
Username = 指定した場合記述
Password = 指定した場合記述
Servercharset = Shift_JIS
Charset = eucjp
Debug = 0
ODBCの動作確認
isql コマンド(unixODBC?)を実行してみて接続できればOK。
isql DSN ユーザ名(省略可能) パスワード(省略可能)isqlコマンド実行例
isql test
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+SQL> select * from テーブル名
+-----------+-----------+----------+
| ID | field1 | field2 |
+-----------+-----------+----------+
| 1 | 990112 | aaaaaa |
| 2 | 21213 | xccccc |
| 3 | 11111 | bbbbbb |
| 4 | 1254 | dddd |
| 5 | 888888888 | 日本語 |
+-----------+-----------+----------+
SQLRowCount returns -1
5 rows fetched
とか出てきてればおk
追記:brodbcドライバの動作に関してですが、TurboLinux 10 x64のisqlコマンドは正常動作しましたが、VineLinux 4.2ではisqlでは全く動作せずセグフォルトで落ちてしまいます。でもPHP経由ではなぜか正常動作しますので、この辺、何が悪いのかがよくわかりません...。
PHPのコンパイル
PHPをソースからmakeしている場合は、ODBC関数を使えるように configure時に unixODBCかiODBCのどちらかを指定する*2パッケージでインストールされていればそのままodbc関数が動作するかもしれせん。phpinfoを確認してodbcが表示されてればOKかと。
例)
./configure 〜省略〜 --with-unixODBC=/usr
make
make install
このあと、httpd を再起動するとODBC関数が利用できるようになる。
注:iODBCを使用する場合は configureで --with-iodbc=/usr/local などと指定します。
テストプログラム
DSN名がtest、ユーザ名・パスワード未設定。テーブル名testの場合のサンプルです。
<?php $con = odbc_connect("test", "", ""); echo "ただいまODBC接続中......<br>"; if(!$con) { die("エラー:ODBC接続に失敗しました!<br>"); } $result = odbc_exec($con, "SELECT * FROM test"); while(odbc_fetch_row($result)) { $id = odbc_result($result, 1); $f1 = odbc_result($result, 2); $f2 = odbc_result($result, 3); echo "$id $f1 $f2<br>"; } odbc_free_result($result); odbc_close($con); ?>
PHPからbrodbc経由でodbc関数を実行してみたが
私が試した環境(TurboLinux 10 64bit)ところでは、たまにsegfaultになるという不安定さが残ってしまってます..実用的な安定感がないのが困ったところ。
↓参考:落ちる
Re: Linux上のPHPからAccessを使うには?
「PHPからODBC経由でMS-Accessに接続できない」(1) Linux Square − @IT
まとめると
ほんとややこしいです。