[Play][Anorm] プレースホルダを使って値を指定するときの注意点

 Anormでは、プレースホルダ({}で指定するやつ)とonメソッドを利用して、SQLに値を動的に埋め込むことが出来るのですが、若干制限があるようです。よく考えたら当たり前なんだけど、ちょっとだけハマったのでメモ。環境はPlay framework 2.1.0 + Scala 2.10。

文字列中のプレースホルダの置換は行われない!

 はい。そのとおりなんですが、文字列中、すなわちSQL中のシングルクォートで囲まれている部分のプレースホルダの置換は行われません。私がハマったのはSQLのGeomFromText関数。

SQL("""
  SELECT *
  FROM table
  WHERE MBRContains(GeomFromText('LineString({ax} {ay}, {bx} {by})'), lat_long);
""").on(
  'ax -> (long - xlen),
  'ay -> (lat - ylen),
  'bx -> (long + xlen),
  'by -> (lat + ylen)
)

 こんな感じのクエリです。要はテーブルの中から座標情報が指定した矩形内にあるデータを取ってくるものなんですが、この時GeomFromTextは文字列を引数にとるので、axやayなどのプレースホルダの置換が行われません。特にエラーも発生しないので気づくまで時間がかかりました。こういう場合ってどうしたらいいんでしょうかね。とりあえず扱うのが数値だけだったので、以下のようにして何とか動くようになりました。

SQL("""
  SELECT *
  FROM table
  WHERE MBRContains(GeomFromText({gft}), lat_long);
""").on(
  'gft -> "LineString(%f %f, %f %f)"
    .format(
      long - xlen,
      lat - ylen,
      long + xlen,
      lat + ylen
  )
)

 なんか格好悪いなぁ…直接クエリに対してformat呼んじゃったほうがよさそうかな。

SQL("""
  SELECT *
  FROM table
  WHERE MBRContains(GeomFromText('LineString(%f %f, %f %f)'), lat_long);
""".format(long - xlen, lat - ylen, long + xlen, lat + ylen))

 「いやいやこうするんだよ!」っていうのがあったら教えて下さい。ちなみに発行されたクエリの確認には [Play][DB]発行されたクエリをコンソールに出力する これをやっておくと便利かもしれません。

0 件のコメント :

コメントを投稿