mikeo_410


SQLite3

名前に引かれて、Debianのバイナリパッケージ php4_sqlite3 の sqlite3.so を、レンタルサーバで試してみました。動作します。
なんとか SQLite2 にしたばかりですが、SQL文がより一般的な SQLite3 にしたいと思いました。レンタルサーバーでのデバッグが難しかったので、今度は手元で動かした上でアップロードしたいと思います。PHP4のレンタルサーバーと手元のPC(Windows xammlite PHP5)で同じように動くことが必要です。

1.現状

SQLite3をレンタルサーバーと手元のPCで同じように使えるようにしたいと思います。もし、レンタルサーバ上でデバッグが不要なものがあれば、異なる方法でもOKです。
こう考えて調べてみました。
方法は3通りあることがわかりました。

  1. PHP5がSQLite3を含むと言うのは、PDOドライバが含まれると言うこと。
  2. pear DBを使う。これはPHPのプログラムなので、レンタルサーバーに、単にコピーすれば動作しました。
  3. SQLiteにPHPインタフェースを付けたものを直接使う。php_sqlite3と言うらしい。
1.1.PDO用ドライバ

PDOインタフェース用のデーターベース対応ドライバとして、php_pdo_sqlite.so、php_pdo_sqlite.dllがあります。
レンタルサーバには、PDOそのものがないので、PDOインタフェースでプログラミングすることはできません。
PDO - ドライバ 間のインタフェースが分かれば、その切り口で使える可能性があります。

1.2.pear DB

pear DBは、PHPで記述されているので、レンタルサーバにコピーすれば使えました。もともと、php4_sqlite3 パッケージは、こうした使い道があって作られたのだと思います。
また、Lumad の cakeにも、dbo_pear.php があり有望です。
ところが、WindowsでPHP5の同様のものがありません。
そこで、php4_sqlite3 をビルドして、php5_sqlite3.dllを作りました。
問題解決と思ったのですが、dbo_pear.php は、動作しない状態でした。関数名や引数名が異なり、動作させたことがないようです。
これを、直し始めたのですが、ここで気が付きました。
pear DBを使う必要はまったくないのです。dbo_pear.php ではなく、dbo_sqlite3.phpを作れば良いのです。
CakePHPのサイトには、dbo_sqlite3.phpがありました。内容は、dbo_pdo_sqlite3.phpでした。PDOのないレンタルサーバーでは動作しません。また、手元のPCでもコピーしただけでは動作しませんでした。

1.3.SQLite3 ダイレクト

そこで、dbo_sqlite3direct.phpを作りました。

1.4.現在の構成

 

 レンタルサーバー

手元のPC 

sqlite3本体

 (sqlite3.soに含まれる)

xammliteのsqlite3.dll

PHP
インタフェース

 sqlite3.so
(php4_sqlite3のバイナリから)

php5_sqlie3.dll
(php4_sqlite3をビルドしたもの)

CakePHP
DBOドライバ

  dbo_sqlite3direct.php
(dbo_sqlite.phpを参考に作成)

2.sqlite との差異

  1. アクサングラーブ(アポストロフィ、バッククオート)が使えます。
  2. コマンドラインやSQL中の文字列のエスケープを処理するようです。驚いたことに、パスも
    c:¥¥root¥¥tmp
    のように、バックスラッシュを2つ打つ必要があります。(DOS窓版)
  3. 型について
    基本的に変更ないようです。ただし、すべて文字列だったのが、適宜、数値を整数型、不動小数点型で記録すると書かれています。
    要するに、「テーブルに属性を設定するのではなく、更新時のデータによって内部的に適切に処理する」と言うことだと解釈します。
    (「タイプアフィニティ」コンセプト)
    ただし、数値を比較する場合は注意が必要なようです。テーブル作成時の型指定を全てしなかったら、
    WHERE published=1
    で、"1"に一致しないと言ったことがありました。(数値フィールドにはINTEGERと書くことにします。)
  4. auto_increment は、エラーになった。INTEGER PRIMARY KEYは、旧来通りのよう。
    create table t3 (id, n,PRIMARY KEY(id));
    もOK。
  5.  CREATE TABLE IF NOT EXISTS テーブル名
    は、同様にエラーになる。
  6. -- シングルラインコメント、/* */ は、有効。
    .read で実行したときには表示されない。
  7.  phpMyAdminの作る、短い形式のINSERT分はそのまま通る。 

 3.dbo_sqlite3direct.php

基本的には、dbo_sqlite.php の中で呼び出す、sqlite_xxx を sqlite3_xxx にすれば良いはずです。

  1. 呼び出しているのは、SQLite3ではなく、php4_sqlite3
    PHPから呼び出せるのは、php4_sqlite3 がPHP向けにオープンにしている関数になります。
    引数や戻り値の型や意味も、PHPインタフェースに依存します。
    sqlite3_exec()の戻りは、booleanです。レコードを読み出すには、sqlite3_query() を使う必要があります。
  2. Lumad CMS が使うフィールド名に依存します。
    フィールド名と型の一覧を要求されますが、型がDBから取得できないのでテーブルを持ちました。
  3. sqliteでは、SELECTにかかれていたフィールド名が、そのまま読み出したレコードにも付与されていたようです。
    実際には、テーブル名そのものではなく、MenuItem.nameのようになっており、MenuItem がプログラム中でインデクスに使われています。
    SQLite3では、テーブル名.フィールド名 の形式では返されず、フィールド名のみが帰ります。
    SELECT文のテーブル名の部分を記憶して、読み出し時に補うようにしました。
  4. この、テーブル名は1つではありません。フィールド名が衝突しています。
    一回のSELECT文で、2つのテーブル、menu_items と content_pages のフィールドを取得します。
    このとき、2つのテーブルで id が重複します。テーブル名がないので、同じフィールド名になります。
    PHPでは、同じインデクスなら何事も無く上書きされるので、1つ少なく読み出されてきます。
    これは、SQLite3の問題ではなく、PHPインタフェース部分の問題なのだと思います。
    解決策として、sqlite3_fetch_array() ではなく、sqlite3_fetch() を使いました。
    この関数は、フィールド名を返しません。しかし、前述のSELECT文の「テーブル名を記憶する」を「フィールド名を記録する」として、読み出し時に使います。
                sq3.Execute("PRAGMA short_column_names = 0;");
                sq3.Execute("PRAGMA full_column_names = 1;");
    とすると、テーブル名が付くことが分かりました。
  5.  レンタルサーバでは、stripos()がないと言われました。
  6. INSERT文を、sqlite3_query()で実行すると、sqlite3_last_insert_rowid()は、常にゼロを返します。

4.php5_sqlie3.dll

SQLite3 の機能は、sqlite3.dll を使えば良いわけですが、PHPからは呼び出せません。PHPとの繋ぎの部分が必要です。
Debianの php4_sqlite3 が利用できました。SQLite3を呼び出す部分はそのままで、PHP4な部分がPHP5になれば良いはずです。
これは、単にビルドし直すだけで良さそうです。ソースは、1つずつ .c  と .h があるだけのシンプルなものでした。

  1. visual studio express で、DLL用のプロジェクトを作成し、php4_sqlite3 のソースを追加します。
    sqlite3のパッケージから、sqlite3.hも追加しました。
  2. 「追加のインクルードディレクトリ」は、以下の通り
    C:¥xampplite¥htdocs¥hogeaaa¥php-5.2.6 に、PHPのソースが展開してあるものとして、 
    "C:¥xampplite¥htdocs¥hogeaaa¥php-5.2.6¥Zend"
    "C:¥xampplite¥htdocs¥hogeaaa¥php-5.2.6¥main"
    "C:¥xampplite¥htdocs¥hogeaaa¥php-5.2.6¥TSRM"
    "C:¥xampplite¥htdocs¥hogeaaa¥php-5.2.6"
    "C:¥xampplite¥htdocs¥hogeaaa¥php-5.2.6¥ext¥standard"
  3. 「プリプロセッサ定義」は、以下の通り
    ZTS;PIC;HAVE_CONFIG_H;PHP_ATOM_INC;WIN32;NDEBUG;_WINDOWS;_USRDLL;PHP5_SQLITE3_EXPORTS;ZEND_WIN32;PHP_WIN32;ZEND_DEBUG=0
  4. 「追加の依存ファイル」は、以下の通り
    sqlite3.lib php5ts.lib

 補足:

  1. php5ts.dll は、PHPのwin32用のバイナリ(php-5.2.6-Win32.zip)から取りました。
  2. sqlite3.lib php5ts.lib は、dllからLIBコマンドで作りました。
  3. PHPのプログラムからDLLをロードするには、下記のようにしますが、任意の場所からロードできませんでした。
    php/ext に入れる必要がありました。
    if (!extension_loaded("php5_sqlite3")) {
     dl("php5_sqlite3.dll");
    }
  4. php/ext に入れる必要があるのは、php5_sqlie3.dll だけです。その他は、一般のDLLと同様です。カレントディレクトリかパスの通ったところに置いてください。

 


Web制作 横浜 不動産 生命保険 荒川区 不動産 無添加住宅