MySQL 3.23 な環境で CakePHP の hasAndBelongsToMany を利用する

  そもそもですが,CakePHP は MySQL 4.0 以上が対象らしいです.
  ただ,公式のドキュメントは見つかっていませんが……

  それでも,MySQL 3.23 な環境で CakePHP を使って,なおかつ hasAndBelongsToMany も使いたい場合の対処法です.
  MySQL 3.23 な環境では,hasAndBelongsToMany を使うとき,SQL のエラーが出ます.具体的には JOIN に失敗しています.

  このとき CakePHP は以下のような SQL 文を発行します.

SELECT  `Tag`.`id`, `Tag`.`tag`
FROM `tags` AS `Tag`
JOIN `posts_tags` ON `posts_tags`.`post_id` = '2'
 AND `posts_tags`.`tag_id` = `Tag`.`id`
WHERE  1 = 1


  MySQL のリファレンスにあるように,JOIN は MySQL 4.0.11 以降で対応なので,この JOIN を INNER JOIN にしてあげればいいわけです.

- ref.: MySQL AB :: MySQL 4.1 リファレンスマニュアル :: 6.4.1.1 JOIN 構文
  http://dev.mysql.com/doc/refman/4.1/ja/join.html

注意:INNER JOIN 構文で join_condition  を使用できるのは、MySQL 3.23.17 以降に限られます。同様に、JOIN  と CROSS JOIN に関しても、MySQL 4.0.11 以降でのみ条件を指定できます。


  ちょうど昨日 CakePHP の最新版 (1.1.14.4797) がリリースされたので,この最新版と,その前のバージョン (1.1.13.4450) での修正箇所を挙げておきます.

- 1.1.14.4797 の場合
  cake/libs/model/datasources/dbo_source.php の 1051 行目を修正します.

--- cake_1.1.14.4797-orig/cake/libs/model/datasources/dbo_source.php    2007-04-06 04:21:05.000000000 +0900
+++ cake_1.1.14.4797/cake/libs/model/datasources/dbo_source.php    2007-04-06 08:46:09.015389000 +0900
@@ -1048,6 +1048,7 @@
                     'joins' => array(array(
                         'table' => $joinTbl,
                         'alias' => $joinAssoc,
+                        'type' => 'INNER',
                         'conditions' => array(
                             array("{$joinAlias}.{$assocData['foreignKey']}" => '{$__cakeID__$}'),
                             array("{$joinAlias}.{$assocData['associationForeignKey']}" => '{$__cakeIdentifier['."{$alias}.{$linkModel->primaryKey}".']__$}')


- 1.1.13.4450 の場合
  cake/libs/model/datasources/dbo_source.php の 1043 行目を修正します.

--- cake_1.1.13.4450-orig/cake/libs/model/datasources/dbo_source.php    2007-02-03 11:55:49.000000000 +0900
+++ cake_1.1.13.4450/cake/libs/model/datasources/dbo_source.php    2007-04-06 09:13:16.018886000 +0900
@@ -1040,7 +1040,7 @@
                 }
                 $sql .= ' ' . join(', ', am($this->fields($linkModel, $alias, $assocData['fields']), $joinFields));
                 $sql .= ' FROM ' . $this->fullTableName($linkModel) . ' ' . $this->alias . $this->name($alias);
-                $sql .= ' JOIN ' . $joinTbl;
+                $sql .= ' INNER JOIN ' . $joinTbl;
 
                 $joinAssoc = $joinTbl;



  上記の修正はあくまで,hasAndBelongsToMany を使いたい場合で,そのほかの項目はあまりテストしていませんのでご注意を.
  可能であれば,MySQL 4.0.x にアップデートするのが一番だと思います.