ZendFramework1 future は PHP8.1 コンパチで動作する、ありがたいライブラリ。(※8.1 も 2024/11/25 で セキュリティサポート が来てしまいますが...)
過去の資産を使い、未だに多くの IBMi ユーザーが PHP 開発で、ZF1 を使用しており、PHPのバージョンアップでは、非常に助かっている。
しかし、旧ZF1時代から、Zend_Db_Adapter_Db2#limitメソッド
に問題があり(※DB2 LUW 試していないのでわかりません)我々が IBMi
で使用する際には、一工夫が必要。
参考リンク
- repo - Shardj/zf1-future
- issue - Zend_Db_Adapter_Db2 limit does not work #391
- PR - Improving limit method using OVER() #392
- PR - Improving limit method using LIMIT,OFFSET #393
問題の箇所
以下の箇所の OVER()
だが、SQLに ORDER BY
がない場合は正常に動作するが、ORDER BY
が存在する場合は OVER(ORDER BY ...)
にしなければならない部分が 抜け落ちている。
-
OLAP の指定
「OLAP-specification OVER( --- window-order-clause --- ) 」
/**
* DB2 does not implement the LIMIT clause as some RDBMS do.
* We have to simulate it with subqueries and ROWNUM.
* Unfortunately because we use the column wildcard "*",
* this puts an extra column into the query result set.
*/
return "SELECT z2.*
FROM (
SELECT ROW_NUMBER() OVER() AS \"ZEND_DB_ROWNUM\", z1.*
FROM (
" . $sql . "
) z1
) z2
WHERE z2.zend_db_rownum BETWEEN " . ($offset+1) . " AND " . ($offset+$count);
上記問題を zf1-future の issue に上げた。 issue - Zend_Db_Adapter_Db2 limit does not work #391
対応
対応としては、OVER(ORDER BY ...)
と、過去には存在しなかったが、今ではDB2でも実装されている LIMIT
の何れかを使用する実装が考えられる。
OVER(ORDER BY ...)
は、過去の DB2 バージョンのユーザーも使えるが、冗長で煩雑に見え、LIMIT
の方は、他のDB製品とも近く、記述としてはシンプルになる。
// Add this piece and place $order in OVER() clause
$pieces = preg_split("/order by/i", $sql);
$order = "";
if(array_key_exists(1, $pieces)) {
$order = "ORDER BY " . $pieces[1];
}
$limit_sql = "SELECT z2.*
FROM (
SELECT ROW_NUMBER() OVER($order) AS \"ZEND_DB_ROWNUM\", z1.*
FROM (
" . $sql . "
) z1
) z2
WHERE z2.zend_db_rownum BETWEEN " . ($offset+1) . " AND " . ($offset+$count);
return $limit_sql;
}
$sql .= " LIMIT $count";
if ($offset > 0) {
$sql .= " OFFSET $offset";
}
return $sql;
}
本体にいつ取り込まれるかは?未定なので、もし limitメソッド
で困っている人は参考にまでどうぞ。
2024.01.26 追記
PR案 Shardj/zf1-future - Improving limit method using OVER() #392 に関しては、一旦マージして貰えました。これで少なくても IBM i で limit,OFFSET の改善にはなりました。Thanks!
こっち Shardj/zf1-future - Improving limit method using LIMIT,OFFSET #393 は現時点で discussion 中です。