Nucleus(JP)フォーラム

NucleusCMS日本語版ユーザーのためのサポートフォーラムです。疑問が生じたらまずは記事検索をご利用ください。

ログインしていません。

#1 2011-06-27 14:59:32

kotorisan
メンバー
登録日: 2007-01-17
投稿: 49

Re: PDO

Mysql以外で
公式にはインストーラーもデータコンバーターも存在しないと思うので
現時点では、どうでもいいことなんですが、

Mysql以外でのデータベースで接続できるようにしてみようかなと
思いソースをみたのですが、

問題点がありました。
バックアップ

nucleus > libs > backup.php
function _backup_dump_structure($tablename)

SQL文の
SHOW CREATE TABLE テーブル名
は、一部のデータベースでは使えないので

コアのbackup.phpに
なんらかの分岐コードで対処する修正が必要のようです。

Sqlite : いくつか方法がありそう。
検索したところFirebird も違うようです?

:shock: 追記: 7/7
  修正してsqliteで動くようにした結果問題点が数カ所ありました。

・sql_real_escape_stringを使う場合は、シングルクオートに統一するか
sql_quote_stringに置き換えが必要。
  コアでは、ダブルクオートのものが混在しているので、
sql_real_escape_stringで検索して、前後のダブルクオートがあればシングルクオート置換する
sqliteやfirbirdなどでは、深刻な問題となります。
この問題の解決なしでは、mysql以外でのデータベースの置き換えは危険です。
  どちらかというとsql_real_escape_stringを sql_quote_stringにしたほうが安全です。

・非標準の使い方をしているINSERT文を修正する必要があります。
  INSERT INTO table SET name1 = value1 ... を
  標準の INSERT INTO table (name1 , name2, ..) VALUES (value1,value2, ..)に修正する
  TEMPLATE.php , SKIN.php

・Mysql以外で使用する場合
  SELECT文でsql_num_rows($res)を使っているものが かなりあるので、それを徹底的に修正する必要があります。
  この問題を解決できない場合は、Mysql以外のデータベースでの運用は困難というか不可能です。

※sqliteでは、SELECT文でsql_num_rowsは、サポートされていません。
※phpのヘルプより引用
ほとんどのデータベースでは、PDOStatement::rowCount() は SELECT 文によって作用した行数を返しません。
代わりに、 PDO::query() を使って 意図する SELECT 文として同様の述部を持つ SELECT COUNT(*) 文を発行し、
PDOStatement::fetchColumn() を使って返される行数を取得することができます。
そうすることで、アプリケーションは正しい動作をすることができます。

・SUBSTRING 、 UNIX_TIMESTAMPがsqliteにはない
sqliteCreateFunctionで対応

・`識別子` 問題
  sqlite3.x系は、互換モードが自動で働くので問題ありません。
  Firebirdなどのデータベースでは、`識別子`→"識別子"に変更が必要。

・mysql特有の予約語

インストールスクリプトを修正して
Windowsローカル環境で
初期サイトをテストしてみましたが、
トランザクションをスクリプトの開始から終了までかけてしまうと
4クリック連打でフリーズ状態になりました(数分間応答しない)。
デフォルトの自動トランザクションのままの場合は、手動クリック連打くらいでは平気でした。

  config.php : 変更箇所
   // default is $MYSQL_HANDLER = array('mysql','');
   // $MYSQL_HANDLER = array('pdo','mysql');
   $MYSQL_HANDLER = array('pdo','sqlite');
   $MYSQL_DATABASE = '/pathto/sqlitedatabase';

自分でプログラミングができない場合は、
現状の仕様では
mysql以外での運用はとても危険。

オフライン

#2 2011-07-07 12:33:15

kotorisan
メンバー
登録日: 2007-01-17
投稿: 49

Re: PDO

libs/sql/PDO.phpは、まだmysqlでも正式対応 表明されていなかったのですね
てっきりmysqlは 問題なく対応が済んでいるのかと思い込んでいました

big_smile 接続部分に関しては、trunc に今日修正してもらえました。
revision 1550 です
http://forum.nucleuscms.org/viewtopic.php?t=20507

今回の修正は、SQLite 版 Nucleus
http://japan.nucleuscms.org/wiki/plugins:nucleus_sqlite
とは全く関係がありません。

コアの機能で切り替えれられるようにテストしたものです。
パッチを小出ししてみました。

7/7の追記部分のパッチを提供できなくはないのですが
既存のmysql関数の動作に影響がないか十分テストできていないので
ほかの大量のパッチは、まだ投稿していません。 :oops:

オフライン

#3 2011-07-08 00:32:07

ftruscot
メンバー
登録日: 2009-01-21
投稿: 28

Re: PDO

kotorisan, I think it's great that you are working to get the the core Nucleus version running on sqlite through the PDO handler. I can't quite follow the details of this thread due to the limitations of Google Translate and my own inability to understand Japanese. I would love to help straighten out any code that is causing trouble as you locate it.

As we get closer to 4.0, we will be making a push for plugin authors to update their plugins to conform to a few recent standards that will let us move forward. One of these standards is being multi-byte compliant using mocchi's i18n class for string manipulation. Another is using the sql_* wrappers for db access. Once we can get the bulk of the popular plugins updated to use the sql_* wrapper functions, it will be much more practical for users to switch to the PDO handler with backends different from mysql (or mysqli).

Thanks again for your work on this problem.

オフライン

#4 2011-07-11 16:22:23

kotorisan
メンバー
登録日: 2007-01-17
投稿: 49

Re: PDO

負荷テスト for sqlite

さくらインターネット スタンダードで 再読み込み連打。

sqliteモード
再読み込みを 秒間4~5クリックの速度で数秒間連打すると
数回に一回
・Forbidden
  You don't have permission to access /dev_root/nucleus_trunk/ on this server.

・503 Service Temporarily Unavailable

mysqlモード
その後 同様に mysql版の運用サイトで連打
秒間3~4クリックで 2秒しないうちに
  Service Temporarily Unavailable
  The server is temporarily unable to service your request due to maintenance downtime or capacity problems.
  Please try again later.
  Apache/1.3.42 Server at ○  Port 80

利用しているプラグインに違いがありますが
cgiモードでphpが動いている
さくらインターネットでは、すぐに落ちるという意外な結果が・・・

同時に5人程度つつくとサーバーが落ちるなんて信じられません。
これには、正直びっくりです。
本年度で
さくらインターネット スタンダード解約することにしました。

ひょっとすると モジュール動作するcore-mini(xrea)のほうがましなのかも?

個人的にcore-mini(xrea)かコロリポあたりに秋頃 サーバー移転しようと思います。

オフライン

#5 2011-07-11 16:24:46

kotorisan
メンバー
登録日: 2007-01-17
投稿: 49

Re: PDO

sql/pdo.phpに
sqliteのエスケープの
sqlite_escape_stringパッチを当ててもらいましたが、
php5.4アルファの告知をみると、ext/sqliteが pecl にいっちゃうとあるので
sqlite_escape_stringを使うのはまずかったかなと思っています。
PDO->quoteの値から substr($s , 1, strlen($s)-2) して
最初と最後の1文字づつを切り落とすほうがよかったように思いました。


//		   return sqlite_escape_string($val); // PHP 5.4 : ext/sqlite moved to pecl
			$s = (is_null($dbh) ? $SQL_DBH->quote((string) $val) :$dbh->quote((string) $val) );
			if ( $s &&  strlen($s) > 2)
			    return (string) substr($s , 1, strlen($s)-2);
			 else
			    return "";

将来的にどんな変更がphpに加わるかわからないので
シングルクオート以外で返ってくると困るので
if (substr($s, 1,1) != "'" ) エラーみたいな処理も念のためあった方が無難かも

オフライン

#6 2011-07-13 11:25:02

kotorisan
メンバー
登録日: 2007-01-17
投稿: 49

Re: PDO

sqliteのテスト用のファイルをアップしました

http://japan.nucleuscms.org/bb/viewtopic.php?f=1&t=4860

オフライン

#7 2011-07-19 11:52:41

kotorisan
メンバー
登録日: 2007-01-17
投稿: 49

Re: PDO

データアクセス、つまりsql_関数を使っていないプラグインも
'SqlApi'を返さないとコアが拒否するようになっているので
問題だと思いますが、それは、別の問題なのでおいといて、

sqlite対応にする場合
現状の仕様では、 プラグイン側で
誤動作・構文エラーなどがおきるおそれとセキュリティ確保ができないので
新しく'SqlApi_sqlite'みたいな名前を追加すると

プラグイン関数の function supportsFeature($what)
で、 'SqlApi' , 'SqlApi_sqlite'の両方でtrueを返すと
sqlite対応とみなすようにすれば、
対応の検出と誤動作防止など、混乱しないで移行できるように思います。

MANAGER.php : _loadPlugin($name)
で SqlApiの確認の後の行に以下をいれれば問題ないように思います。

// unload plugin if using non-mysql handler and plugin does not support it
global $MYSQL_HANDLER;
if ( (!in_array('mysql',$MYSQL_HANDLER))
  && !$this->plugins[$name]->supportsFeature('SqlApi_'.$MYSQL_HANDLER[1]) )
{
    unset($this->plugins[$name]);
    ACTIONLOG::add(WARNING, sprintf(_MANAGER_PLUGINSQLAPI_NOTSUPPORT.$MYSQL_HANDLER[1], $name));
    return 0;
}

上記で試験的にテスト中です。


データ移行の課題
いくつか考えてみたのですが
・テーブル構造がデータベースによってかなり違う
これが一番の壁です。
データ移行には、テーブル構造などが必要ですが、
機械的にテーブル構造を変換するには、高度なプログラミングを必要とするので
難易度を下げるためにも
テーブル構造をプラグインが返してくれた方が簡単確実なので
plugin関数に dump_structure($database_type = 'mysql')
みたいな感じで、
必要なCreate table文やCreate index文を配列で返すようにしてもらえば、
データベース間のデータの相互移行は比較的簡単にできると思います。
・データベースに左右されないxml形式でバックアップする共通仕様を作るのもいいかもしれないです。
メモリ制限や実行時間制限の問題あり。
・テーブルを作成するクラスを作り、それに列名などの情報を登録してもらい、
データベースに応じた適切な作成文を自動で返す。
・なんとなく自動適当変換
制約などを間違った場合、誤動作につながる。
・ほかのソフトで自動変換してもらう。

オフライン

Board footer