KinoWiki を pdo_sqlite で

FedoraPHP ってば sqlite モジュールが添付されていません。でも KinoWiki 2.1 は PDO インタフェースじゃなくて sqlite_* インタフェースを使ってるんですね。

PHP のソースをもってきて sqlite モジュールをビルドすればいいんですが,KinoWiki のほうを書き換えて対処してみようと,がんばってみました。

パッチ更新しました。詳しくは後述。

--- hideable/database.inc.php.orig	2005-12-06 18:18:22.000000000 +0900
+++ hideable/database.inc.php	2007-03-27 10:14:54.000000000 +0900
@@ -4,5 +4,10 @@
  */
 
-
+function _sqlite_php_function()
+{
+	$arg_list = func_get_args();
+	$method_name = array_shift($arg_list);
+	return call_user_func_array($method_name, $arg_list);
+}
 
 /**
@@ -38,6 +43,9 @@
 	{
 		$file = WIKIID . '.db';
-		$this->link = sqlite_open(DATA_DIR . $file, 0666, $error);
-		if($this->link == false){
+		try {
+			$this->link = new PDO('sqlite:' . DATA_DIR . $file, null, null, array(PDO::ATTR_TIMEOUT => 5000));
+			$this->create_function('php', '_sqlite_php_function');
+		}
+		catch (PDOException $error) {
 			clearstatcache();
 			if(is_writable(DATA_DIR) == false){
@@ -51,5 +59,4 @@
 			}
 		}
-		sqlite_busy_timeout($this->link, 5000);
 	}
 	
@@ -61,8 +68,8 @@
 	{
 		if($this->transaction > 0){
-			$this->query('ROLLBACK');
+			$this->rollBack();
 		}
-		if($this->link != false){
-			sqlite_close($this->link);
+		if($this->link != null){
+			$this->link = null;
 		}
 	}
@@ -77,6 +84,6 @@
 	function query($query)
 	{
-		$result = sqlite_unbuffered_query($this->link, $query);
-		if($result == false){
+		$result = $this->link->query($query);
+		if($result === false){
 			throw new DBException('クエリを実行できませんでした。', $query, $this->link);
 		}
@@ -93,6 +100,6 @@
 	function exec($query)
 	{
-		$result = sqlite_exec($this->link, $query);
-		if($result == false){
+		$result = $this->link->exec($query);
+		if($result === false){
 			throw new DBException('クエリを実行できませんでした。', $query, $this->link);
 		}
@@ -111,5 +118,7 @@
 		//	http://bugs.php.net/bug.php?id=29339
 		//	http://bugs.php.net/bug.php?id=29395
-		return $str == '' ? '' : sqlite_escape_string($str);
+		if ($str == '')
+			return '';
+		return substr($this->link->quote($str), 1, -1);
 	}
 	
@@ -132,5 +141,5 @@
 	{
 		if($this->transaction == 0){
-			$this->query("BEGIN TRANSACTION");
+			$this->link->beginTransaction();
 		}
 		$this->transaction++;
@@ -145,5 +154,5 @@
 		$this->transaction--;
 		if($this->transaction == 0){
-			$this->query("COMMIT");
+			$this->link->commit();
 		}
 	}
@@ -169,8 +178,8 @@
 	{
 		if($num_args === null){
-			return sqlite_create_function($this->link, $function_name, $callback);
+			return $this->link->sqliteCreateFunction($function_name, $callback);
 		}
 		else{
-			return sqlite_create_function($this->link, $function_name, $callback, $num_args);
+			return $this->link->sqliteCreateFunction($function_name, $callback, $num_args);
 		}
 	}
@@ -183,8 +192,8 @@
 	{
 		if($num_args === null){
-			return sqlite_create_aggregate($this->link, $function_name, $step_func, $finalize_func);
+			return $this->link->sqliteCreateAggregate($function_name, $step_func, $finalize_func);
 		}
 		else{
-			return sqlite_create_aggregate($this->link, $function_name, $step_func, $finalize_func, $num_args);
+			return $this->link->sqliteCreateAggregate($function_name, $step_func, $finalize_func, $num_args);
 		}
 	}
@@ -199,5 +208,5 @@
 	function fetch($result)
 	{
-		$ret = sqlite_fetch_array($result);
+		$ret = $result->fetch();
 		if(get_magic_quotes_runtime()){
 			return array_map('stripslashes', $ret);
@@ -215,5 +224,5 @@
 	function fetchall($result)
 	{
-		$ret = sqlite_fetch_all($result);
+		$ret = $result->fetchAll();
 		if(get_magic_quotes_runtime()){
 			return map('stripslashes', $ret);
@@ -232,5 +241,5 @@
 	{
 		$ret = array();
-		while(($str = sqlite_fetch_string($result)) !== false){
+		while(($str = $result->fetchColumn()) !== false){
 			$ret[] = $str;
 		}
@@ -259,5 +268,6 @@
 		}
 		
-		parent::__construct($mes, linetrim($hiddenmes . "\n") . sqlite_error_string(sqlite_last_error($dblink)));
+		$error_infos = $dblink->errorInfo();
+		parent::__construct($mes, linetrim($hiddenmes . "\n") . "\n" . $error_infos[2]);
 	}
 }


でもこれだけではだめで,hideable/fuzzylink.inc.php の 155 行目あたりにて

$result = $db->query("SELECT DISTINCT pagename FROM fuzzylink_list WHERE php('mb_ereg', '(?:^|/)' || exp || '$', '$_word') ORDER BY pagename");

こんなコードがあってひっかかりました。PHP でそんな拡張してたんすか。がーん。

仕方ないので,とりあえず

$result = $db->query("SELECT DISTINCT pagename FROM fuzzylink_list ORDER BY pagename");

みたく WHERE 句をとっぱらいました。で,PHP 側でコードを書けばいいんでしょうが,この後ファジーリンクまわりは削除しまくりました。


PDO::sqliteCreateFunction() で php というユーザ関数を登録してあげることにしました。これでどうやら他所を修正しなくともうまく動いている模様。ほんとは引数が正しいかどうかとかチェックしないといけないと思うんですが。