LoginSignup
12
11

More than 5 years have passed since last update.

scalikejdbcで独自の型を扱う

Last updated at Posted at 2015-04-12

TreasureDataをscalikejdbcで操作するときに、独自のカラム型に対応する方法を試す。

TreasureData(presto)には、Arrayのカラムが使えてvarcharやintを入れられる。

取得すると、[1,2,3]のようなjson形式の配列で返ってくる。

独自の型とテーブル

型とテーブルの構造は以下とする。

case class TDArray[A](values: Seq[A])
case class Foo(
  id: Int,
  arrStr: TDArray[String],
  arrInt: TDArray[Int],
  time: Long)

object Foo extends SQLSyntaxSupport[Foo] {
  override val tableName = "foo"
  override val columns = Seq("id", "arr_str", "arr_int", "time")
  def apply(rn: ResultName[Foo])(rs: WrappedResultSet): Foo = autoConstruct(rs, rn)
}

これをreadする。

object FooDao {
  val f = Foo.syntax("f")
  def read(id: Int)(implicit session: DBSession = AutoSession): Seq[Foo] = {
    withSQL {
      select
        .from(Foo as f)
    }
      .map(Foo(f.resultName))
      .list().apply()
  }
}

このままだと、TDArrayをどうしたらいいか分からないのでエラーになる。

結果セットから、値を取得するときにTypeBinderを経由して取得しているようなので、TypeBinderに独自の定義を追加すればいい。

型クラスになっているので、implicitで型を定義する。

object TDArray {
  val stringTypeBinder: TypeBinder[TDArray[String]] = {
    TypeBinder(_ getString _)(_ getString _).map { s =>
      if (s == null) TDArray(Seq[String]())
      else TDArray(s.init.tail.replace("\"", "").split(',').map(_.trim))
    }
  }

  implicit val tdString: TypeBinder[TDArray[String]] = stringTypeBinder
  implicit val tdInt: TypeBinder[TDArray[Int]] = stringTypeBinder.map { tda => TDArray(tda.values.map(_.toInt)) }
}

jsonのパースの所はてきとう。

これでreadできるようになった。

もうちょっと説明

まずFooのapplyで使っているautoConstructのマクロで、WrappedResultSetのgetを呼ぶコードを作っている。

WrappedResultSetのgetは、TypeBinderを取得してapplyしてる。構文が分からない場合は"scala 型クラス"でググルとよろし。

なので、TypeBinderのimplicitを定義すればいいというわけだ。

おわり

追記

ちなみにWrappedResultSetのarrayは、TreasureDataのJDBCドライバがgetArrayをサポートしていないのでUnsopported..の例外になる。╭(°ㅂ°`)╮

(´-`).。oO(TreasureDataよく分からん...)

12
11
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
12
11