CakePHP データベースを伴うWEBサイトの管理に便利なCakePHPの小技をご紹介

CakePHP + Oracleにおける4,000バイト制限をどうにかする

2015年6月26日
この記事は掲載から1429日経過しています。
情報が古い可能性が有りますのでご了承下さい

以前も触れましたが、CakePHP + OracleでWEBシステムを構築する案件を進めています。

そもそもCakePHPはデフォルトでOracle用のドライバーが用意されておらず、有志が作成したものを使うしか無い状況に加え、date形式のカラムへの日時のインサートがそのドライバーでは対応出来ないという、厳しい状態です。

結局、単純な呼び出しはCakeを使う事が出来るものの(それでも日付は時間が取り出せない)、インサートやアップデートはモデルを使わずにsqlを走らせるしか無いようです。

例えば以下のような感じ

Cakeの縛りから開放されますので、複雑なjoinなども割と容易く実行出来ます。

さて、Oracleには発行するSqlに4,000バイトの制限が掛かっており、これを超えるとエラーとなります。
ORA-01704: 文字列リテラルが長すぎます

これがとても大変というか、そもそも日本語は2~4バイトあるので単純に2バイトとしても2,000文字、しかもsql文もこれに含まれるので、送信する文字列は更に少なくなります。

こういう場合はlob系を指定し、別な場所に格納する、という事らしい
http://www.shift-the-oracle.com/table/lob-storage.html

そもそも日本語はUnicode+PHPだと4バイトになる文字も有り、そうなるとフォームから送信出来るデータは、500文字程度にしないと安心出来ない。500文字って、ちょっとしたお問合せ内容なんかだと簡単に記入する量なので、そもそも無理があるのだと思います。

Googleなど大手でもMySQL(現在はmysql派生MariaDB)をチューニングして採用しているなど、WEBサービスではMysqlやPostgresの方が取り回しが楽なのです。

ですが、クライアントからcake+Oracleを指定されている以上はどうしようも有りません。

今回のテーブルの構造と制約

テーブルを変更する際に、それを上長が許可する事で実行される、いわゆるワークフローが必要で、新旧データを格納するテーブルが必要になります。更新がいつ行われ、どのデータをどう変更したか、誰が承認したかなどを記録する為のテーブルです。

また、これには個人情報が含まれる可能性が有り、暗号化も必要になります。但し、用意してくれたOracle暗号化classは単純な同一文字列での暗号化で、rijndael-256のようなものではなく(これはパッケージ会社の指定)、ちょっと怖い。ですので、cakeで暗号化して保存します。

Crypt.php

暗号化用の共用classを作成するため、Vendorあたりに適当なファイルを作ります。

beforeSave

該当モデルのbeforeSaveで、新データ(new) 旧データ(old) の処理を行います。

1) gzdeflateで文字列を圧縮する
2) Crypt::encryptで暗号化
3) base64_encode

AppModel

データを呼び出すとき、そのままでは意味不明な文字列ですので、AppModelへ復号化などを行う処理を書きます。

暗号化のときの逆をやる、という事です。

当初はシリアライズするなど、色々手を考えてみたのですが、どちらにしても文字列が多くなれば4,000バイトに引っかかってしまうので、これまであまり使う機会の無かったgzinflateを使う事で圧縮しました。

gzinflateそのものは日本語でテストすると、圧縮比9でだいたい1/3程度に圧縮されるようです。

だいたい50カラム程度のテーブルの新旧履歴を格納しても大丈夫なので、テキストエリアをある程度の文字数に制限すれば、よほどの事が無い限り大丈夫そうです。

 

Oracleを使ったWEBシステム構築の経験が有る、とは言えない程度しか経験が無いのですが、改めて勉強をしつつ開発を進めると、どうにもこうにも扱いづらい。

オラクルマスターには最高のRDBで、これ以外は無いと思えるほど素晴らしいのでしょうが、WEBベースで考えると正直、使えない子としかまだ思えません。ましてそれをCakePHPという縛りの中でやるのは、指定が無い限りやめた方が良いと思われます・・・Symphonyやzendあたりでもおそらくこの解答になりそうな予感

 

 
  • このエントリーをはてなブックマークに追加
  • LINEで送る

PAGE TOP