二重submit防止のjavascriptをjQueryで。

「ボタンの二度押し対策」とか「二重送信の防止」と呼ばれる設計は、Webアプリにおいてとても重要だ。

なんでもかんでもダブルクリックするユーザーというのは驚くほど多くて、そうした人々はデスクトップ上のアイコンとWebページ上のsubmitボタンとを区別しない。 あるいはsubmitボタンを押したあとで十数秒たっても反応が無い=ネットワーク遅延とかサーバがのろいとか=の場合にも、もう一度ボタンを押したくなるのは当然の心理だろう。

二度押しの結果として同じ商品が2個届いてしまうような事態は避けたい。だからこそ、Web業界ではいろいろと対策が練られてきた。input type=hiddenのタグとサーバ側セッション情報とに同じトークン文字列を持たせて云々、というのがサーバ側での定番の手法。そして、クライアント側ではJavaScriptを使った手法が様々に考えられている。 サーバ側での対応は、アプリの誤作動や、それこそ注文伝票が2枚発生してしまうのを防ぐためだ。一方クライアント側での対応はユーザビリティ向上の側面が大きい。どっちの対応も正しく、そして必ず両方とも実装する必要がある。

ここではクライアントサイドでJavaScriptを使う手法の話をする。何年も前に議論がなされていて、すでに枯れた話題ではあるのだが、ブラウザは多様化(特に携帯とか)し、JavaScript開発での汎用ライブラリの活用は当たり前になってきたこの時代、どんな方法がシンプルかつベターなのかという観点で、あらためて手法の一つを紹介したい。

数ある方法論のなかで、最近気に入っているのが、これ。

jQuery Disable On Submit Plugin | EvanBot

/* * jQuery Disable On Submit Plugin * http://www.evanbot.com/article/jquery-disable-on-submit-plugin/13 * * Copyright (c) 2009 Evan Byrne (http://www.evanbot.com) */ $.fn.disableOnSubmit = function(disableList){ if(disableList == null){var $list = 'input[type=submit],input[type=button],input[type=reset],button';} else{var $list = disableList;} // Makes sure button is enabled at start $(this).find($list).removeAttr('disabled'); $(this).submit(function(){$(this).find($list).attr('disabled','disabled');}); return this; }; 使い方↓(head内のscriptタグで) $(function(){ $('form').disableOnSubmit(); // 全てのformに作用させる場合 $('#hoge').disableOnSubmit(); // 特定のid属性をセットしたformタグに作用させる場合 $('.hoge').disableOnSubmit(); // 特定のclass属性をセットしたformタグに作用させる場合 });

submitボタンを押した瞬間にそれをdisabled(グレイアウト)にすることで二度押ししようにもできなくする、jQueryを使ったスクリプトである。おすすめする理由は次のとおり。

  1. jQueryだから。どうせ他の部分でもjQuery使っていることがあるので、そのついででシンプルなスクリプトで済むのなら、気分的にもラクだ。
  2. オリジナルにスクリプトを書こうとして素直に disabled=true とやるだけだと、次にいったページから「戻る」ボタンで戻られるとdisabledになったまま(Firefoxの場合)というワナがあるのだが、こいつはその点も考慮されている。
  3. どのformに作用させるかを、html側のデザイン次第でどうにでもできる。ページ内の全てのformではなく特定のformにだけ使いたいという場合もあるだろう。
    • 例えばform id="foo"とform id="bar"の二か所だけに絞りたければ、
      $('#foo').disableOnSubmit();
      $('#bar').disableOnSubmit();
      と2行書けばいい。
    • HTMLでは、id属性はwebページ内での重複が許されない。同一ページ内に複数のformがあって、それらにいちいち違うid属性を与えるのが面倒だというのであれば、class属性を使うのがいいだろう。form class="foo" というclass属性を与えたformタグすべてに対して作用させたければ
      $('.foo').disableOnSubmit();
      の1行で済む。また、cssではclass属性はタグに複数個設定できる。つまり form class="aaa bbb" みたいにできるのだから、なんだったらデザイン(見栄え)制御用のclass属性とは別にdisableOnSubmit()専用のclass属性を追加してしまえばいい。
  4. form onSubmit="hogefunction()" のようにonSubmit属性でJavascriptを呼び出す手法をよく見かける。しかしこれはちょっと危険で、ブラウザの種類によってはJavaScript関数どころかform全体が動かなくなるケースがあるらしい。少し古いケータイ向けフルブラウザに多い。これはinput type="submit" value="hoge" onClick="hogefunction()" のようにonSubmitではなくonClickでやっても似たような危険が伴う。ケースバイケースなのでなんとも言えないが、少なくとも formタグにはid属性やclass属性を指定するだけという手法ならその部分は普通のHTMLに過ぎない。よって、特殊なブラウザであっても動作不良を起こす可能性が低くなるんじゃなかろうかと。
  5. すぐにやめられる(笑)。「やってみたけど気にいらなかった」というときは、headタグ内のJavaScriptを消すだけだ。使わないid属性やclass属性をformタグに残したところで、どんなブラウザであれ動きにも見栄えにもまったく影響は残らない。

なお、クリックしたときにsubmitボタンをdisabledにしてしまう、という手法それ自体に、 「submit ボタン disable 技の罠 - naoyaのはてなダイアリー」という問題があることは一応頭にいれておいたほうがいい。 しかし、submitボタンのvalue値でサーバ側の動作が変わるような設計は意外と見かけない。つまり、submitボタンのvalue値は「ボタン上に表示される文字」としてしか使ってないケースのほうが多いのではないだろうか。だとすると、そう深く心配するほどでもないだろう。

さらに、これはもはや蛇足だろう(であってほしい)が、下のような書き方をしているformでは、この方法は動作しない。

<table>
<form action="...">
<tr>
......

HTMLとしてありえない位置にformタグがある。 Transitionalならいいのかもしれないけど、strictなdoctypeだとするとおかしい。 そしてjQueryはstrictな方針でDOM要素をたどっていく(らしい)ので、こういう非準拠な書き方をされるとdocumentの中のform要素をうまく捕捉できないことがある。結果、このformではdisableOnSubmit()が動かない。 「formタグの上下に空白ができてしまうんだ、どうしたらいい?」という相談に対する答えとして、ひと昔、いやふた昔前くらいにごく一部のWeb屋の間で流行ってしまった手法だ。 CSSくらい使えよと。(正解は、form style="margin:0;" でいい) 古いページ/デザインだといまだにこういうのが残っていたりすることも頭の隅にいれておこう。

さくらインターネットのサーバ管理画面の認証用Cookieは認証してから3年たっても有効な件

結局、何も改善されてはいない。 ガンプラーウィルス対策のお願い? サーバのパスワードの変更? 安全なWebサイトの作り方改訂第4版? むなしいね。 レンタルサーバそのものの管理画面のセキュリティがこんななんだから、それを使う側がなにやったって無駄だよ。

ことの発端は「さくらインターネットの会員メニュー画面のセッション情報はログアウトしても1年たっても消えない件」という、筆者が2007年に書いた記事にさかのぼる。そして詳細はその一週間後のさくらインターネットの社長自身のブログで実にこと細かにつづられることになった。

焦点となった認証用Cookieは、いわゆる一般的なWebアプリのセッション維持Cookieと比べると構造や設計が(悪い意味でなく)異なる、という点で恥ずかしながら筆者には誤解があった。 そして結局のところ、その認証用Cookieの値に含めた認証日時に対するサーバ側での有効期間をどの程度の長さにするかの問題である、という帰着点を得たはずだ。(※Set-CookieヘッダのExpire属性の話ではないので勘違いしないように) この点については社長ブログでは次の1行にまとめられている。

現在の有効期限を今より短くしないといけないページがあるのかもしれない(コンパネ等)

さて、このとき、当の社長が筆者へメールを寄せている。メールを公開してもよいとのことだったので、3年後のいま、その一部を公開しよう。

(中略)以上のとおり、相当に長い期間が経過した後にクッキーが利用できるのでは ないかという指摘については、クッキー自体に改ざん不可能な形で発行日が含まれており、そのチェックが行われているために、実際にはいつまでも利用できるわけではないということをご理解頂ければと思います。 もちろん、ページ毎に設定されている有効期限については、人によってさまざまな考えがあると思いますので、こちらについては熟慮を続けていければと思います。

そろそろツッコミを入れるべき時だろう。「いまより短く」?「熟慮を続けて」? 「短く」とか「熟慮」とかじゃなくて、「有効期限なんてない/認証用Cookieにその認証時刻も暗号化されて格納されているけどそんなもの見てない/熟慮する気はまるでない」の間違いだったのではないでしょうか。

少なくとも、古い認証用Cookieを使って会員メニューに入ってから契約しているサーバーのコントロールパネルのファイルマネージャ(エクスプローラっぽいやつ)の画面にたどり着いてファイルを削除または編集するまでの一連の流れを見ると、そうとしか思えない。再現手順は3年前の記事と同じで、次のとおり。

  1. さくらインターネットのユーザーの契約情報などを見る画面において、ログインする。
  2. cookie情報を参照し、secure.sakura.ad.jpドメインで発行されている「SID」というCookieに格納されている値をメモ帳かなんかにコピペして保存しておく。
  3. 画面右上の「ログアウト」ボタンを押す。念のためブラウザ内のすべてのCookie情報を削除し、さらにブラウザを閉じる。
  4. 30分または24時間または3日または3年待つ。どれでも結果は同じ。
  5. 待った後、再びメニューの画面にアクセスする。IDとパスワードの入力を促す画面が出ることを確認する。そこで、Cookie情報を手作業で追加、編集する。具体的に言うと、上でメモっておいた値をSIDというCookie名で保存する。ドメインはsecure.sakura.ad.jp、パスは/、secureフラグはオンにして、期限は適当に1年後くらいの日時にしておく。
  6. その状態で改めてメニューの画面にアクセスする。IDやパスワードを入力してないにもかかわらずログインした状態での画面が現れる。
  7. 「サーバーの解約」をしようとすると、パスワードの再入力画面が現れる。どうやらそういう画面では認証用Cookieの値に仕込まれた時刻情報をちゃんとチェックしているようだ。
  8. しかし、「サーバー設定」を押すと、素直にサーバーコントロールパネルの画面に遷移する。 そして「ファイルマネージャ」にアクセスすれば、エクスプローラーライクな管理画面に遷移する。ファイルの表示も削除も編集も自由自在。

なお、「会員情報」のページからパスワードを変更しても、同じ手順が可能だ。つまり、認証用Cookie(値はまとめて暗号化されている)の中には、パスワードそのものの情報は含まれておらず「ID(会員番号?)とその認証が成功した日時」の情報が入っており、それだけで判断されるようになっているわけだ。

それから、「Cookieの中身をコピペして保存するような手法まで気にしろというのか」という話をする者は、問題点をまるで理解していない。

少し話を変えて、わかりやすい事例を挙げよう。最近、ガンプラーというコンピュータウィルスが猛威を振るっているそうだ。 その亜種は、「「FFFTP」のパスワードが“Gumblar”ウイルスにより抜き取られる問題が発生 (Internet Watch 2010/1)」 といった悪さをする。 なんにせよ、特定のFTPソフトがOSのレジストリに書き込んでいる情報を狙ってパスワードを盗み取るくらいだ。 特定のレンタルサーバ会社を狙ってブラウザのCookie情報を盗み取るようなことが、より難しいとも突飛なアイデアだとも思えないし、そういう亜種の出現もそう遠い未来ではなかろう。

一般論としては、WebサイトのCookieを盗まれることはめちゃくちゃに危機的と言えるほどの脅威ではない。Cookieの情報というものはあくまでも「一時的」な意味合いのものがほとんどだからだ。

ただしそれは、Cookieの値としてのセッションIDないしはそれに類する認証情報の、「いつ発行したか」の値をちゃんとチェックしかつ古い認証情報をはじくという仕様がWebサイト側に実装されていれば、の話である。

また、例えばFTPのパスワードであれば、盗まれたと気づいた段階で慌てて別の安全なPCからパスワードを変更にかかればよいかもしれないが、前述のとおり、さくらインターネットの認証用Cookieは、パスワードを変更した後でもそれ以前に発行されたCookieさえ手元にあれば認証を通過できてしまう。少なくともサーバーのコントロールパネルやファイルマネージャ画面までは。 これをどう救えというのだろう。

認証結果の有効期限といったものは、未知の脅威にもなんとか耐えうるための概念であり設計思想だ。 しかし、現状のさくらインターネットのサーバーコントロールパネル機能(にたどり着くまでの認証機能)を見る限り、そういった基本的な設計思想というものが完全に無視されている。 レンタルサーバ会社の社長自身が実に細かく問題点を把握しかつそれを自分のブログで公開し、おっ、社長すげえ、とか一見そう思えたのだが、現状を見るに、実は根本レベルでの理解がまるで欠けていると感じざるを得ない。

有効期限なし(無期限)という実装の問題はもちろん、それをはっきり認識し、かつ、責任者としての自分のブログで問題点を広く公開しつつも、結局はさらに数年も放置するという行動は、ユーザーの利便性のためとかいうトンチンカンな言い訳で済むような次元をはるかに超えている。

続:さくらインターネットのサーバ管理画面の認証用Cookieは認証してから3年たっても有効な件

本編と続編を同時に公開する理由?ためしにやってみただけであり、気分です。とくに意味は無い。

いまさら昔の話を蒸し返すようなことをするくらいなら、2007年当時に本編みたいな議論を続ければよかったじゃないか、と思う方がいらっしゃることかと思う。

ぶっちゃけ、こうなるとは思っていなかったのである。なんせ責任者(社長)が出てきてこと細かに説明し始めるという予想外の展開になったうえ、問題点がはっきりしたからにはなにかしら手をつけてくれるのだろうと思うじゃないですか。

そんなわけで、事後検証は数ヵ月後くらいにまたやろーと思ってほったらかしていたら、見事そのまんま(俺が)忘却の彼方。で、何年もたった最近になってMTのバージョンアップを試みているうちに(20分でめんどくさくなって挫折)、DBのなかをあれこれと覗いていて昔の件の自分のエントリを見かけて、「ハテ、そういえばあれはどうなったのだろう?」と思い出してもいっかい試してみたら、何ひとつ改善されていないことが判明して唖然とした次第。もうね、アホかと。

俺はセキュリティの専門家と呼べるほどの技量ではないしそっち系を目指してるわけでもないが、こんなのをほったらかすことがまずいことくらいはわかる。コンピュータセキュリティの世界で「フルディスクロージャ派」とそうでない派の議論があるのは知っていたが、なんでそんな議論になるものなのか?という理由の一端を身をもって感じることができた。

そこのお前、話が続編になってないぞとか言うな。

iTunesストアでアカウント乗っ取られて不正購入が発生の件

AppleのiTunes ミュージックストアでアカウント乗っ取りが発生して身に覚えナッシングな請求が何万円もきて涙目な人がかなりの数出ているそうで。 当事者の日記とか新聞報道とか、被害者じゃないけどちょっとしたつぶやきとか、ざっと並べてみましょう。

種々の情報に当たるといくつかヒントが得られる。たとえば上の朝日の記事では、引用すると、

一方、愛知県の男性は昨年末まで約2週間、iTS上で、神奈川県の男性の利用画面に入ってしまった。
 神奈川の男性がIDとパスワードを登録する際、同じ名字の愛知の男性のメールアドレスを自らのIDとして誤入力した。そのIDがメールのあて先となったため、登録完了通知などのメールが愛知の男性に送信された。
 愛知の男性が受信メールを基にパスワードを変えると、神奈川の男性のクレジットカードで買い物ができる状態になった。ただ、愛知の男性が神奈川の男性に連絡をとり、IDとパスワードを直した。
 いずれのケースも、悪意を持ってなりすますことができる状態だった。

とのこと。これもひとつのヒントだ。

では、いつもはツタヤでCD借りてくる派なのだが、久々にiTunesストアを覗いてみることにする。

まさにこれが、焦点となっているIDとパスワード。購入ボタンを押すと出るダイアログだ。
「あれ?俺のIDとパスワードってなんだったっけ....?!?!」
と思ったので、とりあえず「パスワードを忘れた場合」のボタンを押してみたら、 ブラウザが立ち上がって次の画面が現れた。(赤線は筆者による)

パスワードを再発行します。あなたのApple IDを入力してください:
(ヒント: Apple ID はメールアドレスの形式である場合も、そうでない場合もあります。たとえば、「yourname」という Apple ID が「yourname@me.com」とは別に存在することがあります。 MobileMe のお客様は、MobileMe のメールアドレスを「membername@me.com」などの完全な形式で入力してください)

唐突ですが、筆者の知人に鈴木N君(あくまでも仮名)という奴がいる。 実験台になってもらおう。自分のAppleIDの欄に「suzukin」と入力してみると。。。

赤い矢印のところにご注目。どうやら鈴木君のメルアドはsuzukin[AT]mac.com のようだ。 そういえば、昨日の電車でしゃべってた外人達が「Hey! Haward...」と言っていた。ハワード君というらしい。そこで、AppleIDの欄に「haward」と入力してみよう。

haward君のメルアドはhaward[AT]gmail.comらしいということがわかった。もちろん本当にそれが鈴木君やハワード君のメルアドであるかどうかは問題ではない。

カンのいい人はこのへんで気づいただろうと思う。

  1. もしも、鈴木君やハワード君は、もうそのメルアドは使ってなくて、失効していて、そして赤の他人が同じメールアドレスを取得できる状態としたら?(それが可能かどうかはメールサービス事業者による)
  2. そして鈴木君やハワード君がiTunesストアで使ったクレジットカードはまだ有効期限内だとしたら?(一般に、クレジットカードの有効期限は3年とか5年とか、結構長い)
  3. そのクレジットカード番号はPC内のiTunesソフト上ではなくiTunesストアのサーバ上に保存されているとしたら?(たぶんそうだと思うんだけど)
  4. 赤の他人が例のメールアドレスを取得しなおして、iTunesストアで「パスワード忘れ」の手続きを踏んでメールを受け取り、パスワードを再設定したら?

しかしそれにしても、責任をもって対処すべき者は誰なのだろう? ユーザー?いやあ、うーん。このケースではそうともいえるし、そうとも言えない。 少なくともいまのiTunesストアのIDとパスワードの管理画面の設計思想には問題を感じる。 大人の事情を重ねるうちに混乱してしまったID体系そのものについても、だ。

あと、購入ボタンを押したときにクレジットカード決済の場合はその都度下4ケタぐらいいちいち打たせる、っていう程度のハードルはつけたほうがいいんじゃないの? それだとユーザビリティ下がるっていうんなら、せめて、クレジットカード(の下4桁)情報のサーバー上での保存を前回入力時から24時間とか48時間といった有効期間を設けて再入力欄出す出さないを制御するとか、方法はいろいろある。有効期間という概念の重要性と有用性については前回書いたさくらインターネットの例のとおりだ。

なお、以上の話はすべて、ほかにも沢山あるであろう仮説のうちのひとつに過ぎない。

see also:

追記:

Outlookのメール上でワンクリックでファイルサーバの資料を開く

なんでもワンクリックを目指さないと気がすまないのはWeb屋の本能である。 ましてや、下のような中途半端な状態だと少し気持ち悪い。

\\資料サーバ\XXプロジェクト\xxの資料\ZZの報告.doc

Windows系のファイルサーバに資料を置いて「このファイルね。よろしく」みたいにメールで連絡するとき、MS-Outlookだと、届いたメールが上のように中途半端なリンク状態で表示されることがある。

下のようにメール本文を書けばOK。あくまでメールの送り手側が気を使ってメールを書く、ということなのだけれど。

  1. メールを書く側(こっちはOutlookとは限らない)で、
    <\\資料サーバ\XXプロジェクト\資料あ\ZZとか>
    <\\資料サーバ\XXプロジェクト\資料あ\ZZとか\ほげほげ.xls>
    のように半角<>で囲うと、メールの受信者側のOutlookの画面上では適切な青いリンク表示になって、一発でフォルダまたはファイルが開く。こんな感じ↓
    <\\資料サーバ\XXプロジェクト\要件定義\ZZサブシステム>
    <\\資料サーバ\XXプロジェクト\要件定義\ZZサブシステム\ほげほげ.xls>
  2. 資料のパスをエクスプローラのアドレスバーからコピペする方法だと当然ながらフォルダ名までしかコピペできません。が、ClipPathをインストールすると、ファイルを右クリックするとそのフルパスをコピペ可能なので便利。しかもOutlook向けに<>で囲ってくれるオプションつき。
  3. なお、VistaとWindows7には(shiftキーを押しながらの)右クリックのコンテキストメニューに「パスとしてコピー」がもともとあるのでClipPathは必要ない。

Outlookが標準メーラーとなっているところでは有効な施策らしい。 知っている人は当然知っていたのだろうけど、いつもメーラーはThunderBirdとかBeckyとかそういうだったので知らんかった。

リクルートスーツ着てるやつってなんなの?

黒だか紺だかのそれは学校指定の制服かい?

俺?もってたよ。典型的なやつを。でもそれは通算でひと月も着てなかったんじゃないかな。とにかく当時の自分ではうまく説明できないような違和感に襲われたから。 でも何かが気に入らないからといって、飲み屋で言やいいのにマイク握って「反省してまーす」とバカ正直に悪態ついてまだ競技で結果も出してない段階で無駄に自己プレッシャーかけるような浅はかな腰ばきパンツDQNではもちろんなかったし、かといって社会人的なスーツ選びのセンスなんてさっぱり。しょうがないからオフィスビル内のエレベータ前のコーヒー屋で小一時間ほど粘って自分と似た背格好と年齢層で社員証ぽいのを首にぶら下げてる人が着てるスーツとシャツの色を見て自分で気に入ったやつを何パターンかざっとメモってから改めてスーツ買いに走ったわけです。

さて、あれからもう何年もたったわけだが、いまはもう不況うんぬんじゃなくて学生が多すぎるという状況。 しょうがねえから学歴で絞って面接する側の人手とあわせてるわけだ。面接に借り出される現場の奴だって自分の仕事の納期とか打ち合わせ資料のチェックとかお偉いさんのための面倒な会議とかあるからそういつまでも時間とれない。

そんな状況じゃ(なくても)、なんだかんだで見た目も結構大きいことくらいうすうすわかってるだろ。かわいいかイケメンかってことじゃなく、面接する側の潜在意識の話。思い出せる奴かどうか、少しでも記憶にとっかかりを残してもらえるかどうか、だ。特に女性は服とメイクと髪型でどうにでも変化をつけられるはずなのに、なんでみんな服も髪型も上から下までおんなじ格好でおんなじような受け答えなの? だったらもう履歴書の写真と学歴欄と成績表とTOEICのスコアだけ見てマルバツつけちゃうだろうよ忙しいのにめんどくせえ。

そもそも新卒の採用って、昨日面接したアイツが職場でたどたどしく客と話をしてる場面を想像したり、あるいはいま面接してるコイツが「XXの○○ってどういうふうにやったらいいんですか?」って仕事の仕方をトンチンカンでもどうにか質問してくるようなケースに結びつけたりして考えてみてさてどうだろうっていうことだろ。もちろんそれだけじゃないけどさ。

なのになんだよそろいも揃ってその格好。おまえら忍者か。間違い探しゲームの駒か。それとも溶け込むような市街戦用迷彩服でサバゲーしにきたのか。さっき面接したキミを思い出してくれるのかなそれで。

今さら性格も成績も変えられないが、服とか髪型なら変えられる。 2月も半ば過ぎてからこんなこと言うのもナンだが、春夏物ならまだ買ってない人も多かろう。グッドラック。

ludiaからtextsearch_sennaへ

PostgreSQLにおけるN-Gram方式の高速全文検索アドオンの話。 SennaはSennaで動きはないのだが、PostgreSQL側で状況が変わってきているのでメモ。

  • SennaのPostgreSQLバインディングであるところのLudiaは、PostgreSQL8.3.5(もしかして8.3.x全部?)あたりからもう動かない。8.4以降もダメで、サポートされる気配もない。
  • そもそもPostgreSQL本体のほうで、GINインデックスと全文検索まわりの組み合わせ方に実装の変更(整理?吸収?統合?)があった。こんな言い方が適切かどうか自信はあまりないんだけど、ver8.3.?あたりから変わったんですよとにかく。
  • そこで、最近のPostgreSQLの共通的な全文検索機構にあわせて作られたtextsearch_sennaがおすすめ。Ludia使いはそろそろこっちに乗り換えるべき。
  • ぱっと試した感じではtextsearch_sennaはludiaよりさらにインストールや設定が簡単(ludiaも十分簡単だったが)であり、しかもSQL文的にはludiaでの検索演算子と同じにできるので、アプリ影響はほとんどないだろう。
  • ところが筆者が試したところ、一つのテーブル上の4,5個のtext型&varchar型のカラムにそれぞれsennaインデックスを張って、SQL文のwhere句で 「col_a %% 'ほげ' or col_b %% 'ほげ'... 」のようにor句でつなぎまくったら、数百回に1回くらいの確率でPostgreSQL自体がSegmentation Fault起こしてpostgresプロセスが全滅。postmasterは生きてるので接続しなおせばすぐ復活するのだが、これにはちょっと参った。 この原因がtextsearch_sennaのほうにあるのかPostgreSQLにあるのかSennaにあるのかはさっぱりわからん(苦笑)。 64bitのlinux(kernel 2.6.18-164.el5)なんだがこのへんも絡んでるのかねえ? とりあえずスタックトレース取って調べてやろうかと思ったけど面倒なので挫折。
  • 自分のアプリを直すほうが話が早くね?ってことで、 目的のテーブルにtext型カラムをひとつ追加して、そのカラムに、全文検索対象にしたい他の複数のカラムの情報を改行でつなぎ合わせてぶち込んでおくことにした。そのカラムだけにsennaインデックスを張り、検索するSQLでは「カラム名 %% 'ほげ'」 のようにするだけだ。よく考えるとこのほうがSQL文がすっきりするしインデックスの数も減ってメンテしやすそうだねということでこれでGO。快適に運用中。
  • もしできましたら早いとこマルチカラムインデックス対応してください^^;) > textsearch_sennaの中の人。
  • なお、textsearch_sennaの場合、「カラム名 %% 'ほげ'」のように特別な演算子を使わなくても 「カラム名 like '%ほげ%'」のような普通のlikeであってもsennaインデックスが効いてくれる。 これ結構うれしい人多いんじゃなかろうか。

ちなみに筆者は形態素解析方式よりもN-Gram方式のほうが好みである。 検索結果に多少のノイズが入るデメリットよりも辞書をメンテしなくていいメリットのほうが大きいので。

see also: