2014年3月 : してログ

PostgreSQL の pg_dump や pg_restore といった CLI 管理ツールは、PowerShell ではうまく動かいないようです。 Windows のコマンド・プロンプトに代わるコマンド・ライン・インターフェイスの PowerShell ですが、コマンド・プロンプトの代わりにはならないということが分かりました。

無理に使おうとした場合、下記のような警告やエラーが出て、作成されたバックアップファイルも壊れています。 Windows Server 2012 では、PowerShell が標準という扱いのようなのですが、似たような見た目に騙されると痛い目に遭います。 マイクロソフトに言いたいのは、もっと保守的にアップデートして欲しい、ということ。 特に、サーバー系 OS はね。

pg_dump を PowerShell で使った場合に出る警告
pg_dump: [カスタムアーカイバ] 警告: ftellで想定位置との不整合がありました -- ftellが使用されました
PowerShell + pg_dump で作ったバックアップファイルを pg_restore でリストアした場合のエラー
[アーカイバ]ファイルヘッダにマジック番号がありませんでした。

単純なバイナリファイルの読み込みだけど、fopen、feof、fread、fclose を使った至ってシンプルな下記のようなコードは危険だ。

$fp = fopen('binary/file/path' ,'rb');
while (!feof($fp)) {
	echo fread($fp,8192);
}
fclose($fp);

これはだいたい上手くいくが、無限ループの危険をはらんでいる。 そのシナリオは、まず、fopen が失敗して $fp に false が入る。 次に、ループ条件が評価され、feof は無効なファイルポインタに対して false を返してしまう。 feof はファイルの終端に達しているかを論理値で返すため、終端でないの意の false と区別がつかない。 従って、無効なファイルポインタを渡されたループは、ファイルをまだ読み終わってないとして、延々と空回りしてしまうことになる。

これを避けるには、ファイルポインタが有効かどうかの判断を加えれば良く、単純に下記のようなコードで良い。 変わったのは、while のループ条件にファイルポインタ自体を加えただけで、ファイルポインタが無効なときは無限ループを回避する。

$fp = fopen('binary/file/path' ,'rb');
while ($fp && !feof($fp)) {
	echo fread($fp,8192);
}
fclose($fp);

なお、ファイルポインタがデータベースの問い合わせで得たバイナリ型のものであってもこれで良さそうだ。 比較関係では書き方や関数があるので、一度ここらへんを見て勉強しておこうと思う。 今更だけれど。

HTML5 で作られたページを IE8 で表示させたときに、互換モードで表示されてしまい、レイアウトが崩れるという事態に遭遇しました。 調べてみると、META タグで互換モードへ落ちるのを防げるらしいので、試してみました。 下記のような記述を、<head> の直後に書いたところ、アドレスバーの脇に出ていた互換モードのアイコンが消えました。

<meta http-equiv="X-UA-Compatible" content="IE=edge" />

PHPExcel はとにかく遅いし、バグも多いのでできれば使いたくないですよね。 でも、xlsx に出すなら使うしかなくて、そんなときはおっかなびっくり使うしか無い、です。 さて、今日はこのエラー「Maximum 31 characters allowed in sheet title」が唐突に出るようになりました。

メッセージからすると、31文字を超えるシート名は使えない、ということになろうかと思います。 しかし、正しく処理できていたエクセルファイルを保存しなおしただけで、このエラーが出るようになったので、訳が分かりません。 念のため、すべてのシートの文字数をチェックしましたが、31文字を超えるものはありませんでした。 Google 先生に聞いてみると、ライブラリに応急手当てして無理やり出ないようにしたという記事が幾つかみつかります。 原因はともかく、私もそれに習って修正してみました。

Classes/PHPExcel/Worksheet.php
	public function setTitle($pValue = 'Worksheet', $updateFormulaCellReferences = true)
	{
		$pValue = substr($pValue, 0, 31); // この行を追加

(追記)この対応をすると、iconv でマルチバイト文字が正しくないというエラーが出ますので、やめた方が良いです。 詳しくは分かりませんが、元のエラーはメモリ不足で出ていたように思います。

jQuery UI Dialog で modal: true としたダイアログで、再表示したときに操作不能になるという現象に遭遇しました。 操作不能というのは、ダイアログに配置したセレクトボックスは選択リストが表示されなくなり、テキストボックスはクリックしてもキャレットすら表示されないという状態です。 ただし、フォーカスは入っているらしく Chrome などで動かすと、枠の色が変わるのが分かります。 ちなみに、モーダルでなければそういうことにはなりません。

色々と調べた結果、作りおきのダイアログがあるとダメなことが分かりました。 問題のあったページでも、そのダイアログとは別に、autoOpen: false として作っておいて、必要なときに dialog('open') しているものがありました。 これを、ボタンやリンクがクリックされた際に、都度作るようにしてみたところ、問題が解決しました。 この現象でお悩みの方は、作りおきのダイアログが他に無いか調べてみてください。