0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【IBM i】ZF1-FutureのDb2対応が改善。ただし古いIBM iでは後方互換性に注意!

0
Last updated at Posted at 2026-11-04

はじめに

2026年11月、PHPのZend Framework 1を継承するオープンソースプロジェクト「ZF1-Future」で、IBM Db2向けのページング処理を改善するPRが正式にマージされました。
今回の改修は、実は私が2023年11月に提出したPRがベースとなっています。
約3年の時を経て、プロジェクトのメンテナーさんによって改良が加えられ、ようやく正式に採用されました。

個人的にはとても嬉しい出来事なのですが、今回の変更では古いDb2との後方互換性が一部失われるため、IBM iを利用されている方に注意点を共有したいと思います。

Shardj/zf1-future - Improving limit method using LIMIT,OFFSET - #393

何が変わったのか?

今回変更されたのは、以下のDb2アダプターです。

  • Zend_Db_Adapter_Db2
  • Zend_Db_Adapter_Pdo_Ibm
    これらのアダプターに実装されているlimit()メソッドのSQL生成方法が変更されました。

従来の処理

これまでの実装では、ROW_NUMBER()を利用し、サブクエリを組み立てることでページング処理を実現していました。

概念的には以下のようなSQLです。

SELECT *
FROM (
    SELECT T.*,
           ROW_NUMBER() OVER (ORDER BY ID) AS ZEND_DB_ROWNUM
    FROM MYLIB.MYTABLE T
) X
WHERE ZEND_DB_ROWNUM BETWEEN 101 AND 120

実際の旧実装では、元のSQLに応じて、さらに複雑な組み立てが行われていました。

今回の新しい処理

新しい実装では、Db2のOFFSETとFETCH FIRSTを利用する方式に変更されました。

SELECT *
FROM MYLIB.MYTABLE
ORDER BY ID
OFFSET 100 ROWS FETCH FIRST 20 ROWS ONLY

非常にシンプルになりました。

現在のDb2.phpでは、以下のように実装されています。

if ($offset === 0) {
    return $sql . " FETCH FIRST $count ROWS ONLY";
}

return $sql . " OFFSET $offset ROWS FETCH FIRST $count ROWS ONLY";

この変更によって、従来必要だった複雑なサブクエリの生成が不要となりました。
また、以前の方式では結果セットに含まれていたZEND_DB_ROWNUM列が、今回の実装では追加されなくなりました。

注意!古いDb2では動かなくなる可能性

今回の変更で注意したいのは、OFFSET構文に対応していない古いDb2では、ページング処理が正常に動作しなくなることです。

メンテナーさんも変更履歴に、以下の対応要件を明記しています。

データベース 必要なバージョン
Db2 for i IBM i 7.1 TR11以降
Db2 for i IBM i 7.2 TR3以降
Db2 for i IBM i 7.3以降
Db2 LUW 11.1以降

IBM i 7.1、7.2では、必要なPTFの適用状況にも注意してください。(※これらバージョンは正規のサポートは終了しているので、本質的にはOSのバージョンアップをすべきかと思いますが...)

どのような問題が起きるのか?

例えば、次のコードを実行する場合です。

$db->limit(
    'SELECT * FROM MYLIB.MYTABLE ORDER BY ID',
    20,
    100
);

新しいアダプターでは、次のSQLが生成されます。

SELECT * FROM MYLIB.MYTABLE
ORDER BY ID
OFFSET 100 ROWS FETCH FIRST 20 ROWS ONLY

OFFSETに対応していないDb2では、このSQLが構文エラーとなります。

ただし、offsetが0の場合は次のSQLになります。

SELECT * FROM MYLIB.MYTABLE
ORDER BY ID
FETCH FIRST 20 ROWS ONLY

こちらは以前から存在する構文ですので、対応している古いDb2でも動作します。

つまり、1ページ目は正常に表示できるのに、2ページ目以降でエラーになる、といった現象が発生する可能性があります。

なお、今回の変更はlimit()メソッドに関するものです。通常のSELECT、INSERT、UPDATE、DELETEなどが、この改修だけを理由に利用できなくなるわけではありません。

古いIBM iを利用している場合は?

IBM i 7.1 TR10以前、または7.2 TR2以前の環境では、今回のOFFSET構文を利用できません。

これらの環境でZF1-Futureのlimit()を利用している場合は、新しい実装への更新に注意が必要です。

対処方法の一つとして、従来のROW_NUMBER()方式を使用しているZF1-Futureのバージョンを継続利用する方法があります。

2026年11月4日時点では、GitHub Releasesに掲載されている最新版はrelease-1.25.2で、今回のPRはmasterブランチに取り込まれた段階です。

ただし、旧バージョンを利用する場合でも、PHPとの互換性やセキュリティ修正の状況を確認してください。

特に、古いIBM iそのものがサポート終了となっている場合は、OSの更新も含めた対応を検討する必要があります。

今回のPRについて

今回マージされたPR #393は、私が2023年11月に提出したものです。当時、Db2 for i向けのページング処理について改善を提案しました。
互換性を重視した別のPR #392は2024年1月にマージされましたが、よりシンプルな実装を目指したPR #393は、その後も残っていました。
今回、メンテナーさんがDb2 for iとDb2 LUWの両方を考慮して実装を改善し、正式にマージしてくれました。
長い間この提案を残し、改良したうえで採用してくださったZF1-Futureのメンテナーさんの皆さんに感謝しています。

まとめ

今回の変更は、Db2向けページング処理をシンプルにする改善です。

一方で、古いDb2との後方互換性は一部失われています。

既にIBM i 7.3以降を利用している環境では、今回のSQL構文の対応について大きな心配はありませんが、古いIBM iを継続利用している場合は注意が必要です。

ZF1-Futureは、今も多くの方々によってメンテナンスが続けられています。

長年使われてきたZend Framework 1を、現在のPHPやDb2環境でも利用できるようにしてくれるコミュニティには、本当に感謝しています。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?