CodeIgniter を MS SQL Server と合わせて使うときに困ったこと

2013.4.29追記: 2番の limit の件について、コメント欄でのご指摘にもとづいて最新の状況を追記しました。開発中の CodeIgniter 3 では、このあたりの修正が不要なように改善されています。

2011.10.24追記: この記事では、CodeIgniter 2.0.3について書いています。

今年のはじめくらいから、仕事でCodeIgniterを使い始めている。
CodeIgniterを選んだ理由はいろいろあるけど、
理由のひとつは「MySQLも、SQL Serverもサポートしている」ということだった。
これは、ユーザーガイドにもしっかり書いてある。
http://codeigniter.com/user_guide/general/requirements.html

ところが、SQL Serverというのはそれなりにクセがあるデータベースで、
CodeIgniterが実際にちゃんとSQL Serverを扱えるか、というところでは
くだらないところではあるけど、多少の問題を感じた。
いくつか、備忘録として書いておこう。


1. 日本語環境でmssqlドライバーは使うべきでないケースが多い。

慣れてる人には当たり前のことなんだろうけど
mssqlドライバーはPHPのmssql関数を使ったドライバーで、
出てくる日本語文字データはShift-JISのみ。
SQL Serverは内部的にはUnicode(UCS-2)で扱っているにも関わらず、だ。
UTF-8が使いたければsqlsrvドライバーを使うしかないんだけど、
CodeIgniterにsqlsrvドライバーが追加されたのは割と最近の話だったのだ...。


2. 実は Active Record で limit が使えない。

普通にページネーションできるだろー、と思ってたら
なぜかできない。
調べてみたら、limitの処理が超適当。

system/database/drivers/mssql/mssql_driver.php Line 640-645
system/database/drivers/sqlsrv/sqlsrv_driver.php Line 572-577


function _limit($sql, $limit, $offset)
{
$i = $limit + $offset;

return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql);
}

いやいやいやいや! それoffsetがoffsetになってないから!
これにはがっかりした...

具体的な対策としては、limitを使う時のみ、
SQL Server 2008 R2 までであれば、 row_number関数を含むサブクエリーを出して
その結果から切り出すようなSQL文字列を作るように
_limit関数の中をいじればOK。
SQL Server 2012 であれば、 OFFSET FETCH でもっとシンプルに記述できます。
http://msdn.microsoft.com/ja-jp/library/ms188385(v=sql.110).aspx


3. sqlsrvドライバーで文字列はUTF-8に指定してるのに、エラーメッセージがShift-JISで帰ってくる。

これは別にCodeIgniterのせいじゃないんだけど、
ドライバーの_error_message関数をアレしてコレするだけで回避できるレベルです。


これ以外の点については、
CodeIgniterは学習コストがすごく低い、良いフレームワークだと思うので
みんなもっとガンガン使うと良いと思います。
でもSQL Serverといっしょに使う時は気をつけましょうね。