Slick Zip Join с HList Shape выходит как Tuple во время выполнения - PullRequest
1 голос
/ 24 апреля 2019

Итак, я пытаюсь реализовать метод zipHList, который похож на Query.zip, но возвращает HLists вместо кортежей.Я начинаю с формы запроса:

implicit class QueryExt[+E, U, C[_]](query:Query[E, U, C]) {
  def zipHList[E2, U2, D[_]](q2: Query[E2, U2, D]): Query[HCons[E, HCons[E2, HNil]], HCons[U, HCons[U2, HNil]], C] = standardHListJoin(q2, JoinType.Zip)

  private[this] def standardHListJoin[E2, U2, D[_]](q2: Query[E2, U2, D], jt: JoinType) = {
    val leftGen, rightGen = new AnonSymbol
    val aliased1 = query.shaped.encodeRef(Ref(leftGen))
    val aliased2 = q2.shaped.encodeRef(Ref(rightGen))
    new BaseHListJoinQuery[E, E2, U, U2, C, E, E2](leftGen, rightGen, query.toNode, q2.toNode, jt,
      aliased1.zipHList(aliased2), aliased1.value, aliased2.value)
  }
}

Затем поддерживающие формы:

implicit class ShapedValueExt[T, U](s: ShapedValue[T, U]) {
  def zipHList[T2, U2](s2: ShapedValue[T2, U2]) = new ShapedValue[HCons[T, HCons[T2, HNil]], HCons[U, HCons[U2, HNil]]]((s.value :: s2.value :: HNil), hconsShape(s.shape, hconsShape(s2.shape, hnilShape))) //Shape.tuple2Shape(s.shape, s2.shape)
}

final class BaseHListJoinQuery[+E1, +E2, U1, U2, C[_], +B1, +B2](leftGen: TermSymbol, rightGen: TermSymbol, left: Node, right: Node, jt: JoinType, base: ShapedValue[_ <: HCons[E1, HCons[E2, HNil]], HCons[U1, HCons[U2, HNil]]], b1: B1, b2: B2)
  extends WrappingQuery[HCons[E1, HCons[E2, HNil]], HCons[U1, HCons[U2, HNil]], C](AJoin(leftGen, rightGen, left, right, jt, LiteralNode(true)), base) {
}

Наконец, поддерживающие HList формы:

object HListShapeSupport {
  final class HListShape[Level <: ShapeLevel, M <: HList, U <: HList : ClassTag, P <: HList](val shapes: Seq[Shape[_, _, _, _]]) extends MappedScalaProductShape[Level, HList, M, U, P] {
    def buildValue(elems: IndexedSeq[Any]) = elems.foldRight(HNil: HList)(_ :: _)
    def copy(shapes: Seq[Shape[_ <: ShapeLevel, _, _, _]]) = new HListShape(shapes)
  }
  implicit def hnilShape[Level <: ShapeLevel] = new HListShape[Level, HNil.type, HNil.type, HNil.type](Nil)
  implicit def hconsShape[Level <: ShapeLevel, M1, M2 <: HList, U1, U2 <: HList, P1, P2 <: HList](implicit s1: Shape[_ <: Level, M1, U1, P1], s2: HListShape[_ <: Level, M2, U2, P2]) =
    new HListShape[Level, M1 :: M2, U1 :: U2, P1 :: P2](s1 +: s2.shapes)

  class HListCaseClassShape[P <: Product, LiftedList, LiftedCaseClass <: P, PlainList, PlainCaseClass <: P](
       mapLifted: LiftedList => LiftedCaseClass, mapPlain: PlainList => PlainCaseClass)(
       implicit columnShapes: Shape[FlatShapeLevel, LiftedList, PlainList, LiftedList], classTag: ClassTag[PlainCaseClass])
    extends MappedScalaProductShape[FlatShapeLevel, P, LiftedCaseClass, PlainCaseClass, LiftedCaseClass] {

    val shapes = columnShapes.asInstanceOf[HListShape[_,_,_,_]].shapes
    override def toMapped(v: Any) = {
      val folded = v.asInstanceOf[Product].productIterator.foldRight(HNil: HList)(_ :: _)
      mapPlain(folded.asInstanceOf[PlainList])
    }
    def buildValue(elems: IndexedSeq[Any]) = {
      val list = elems.foldRight(HNil: HList)(_ :: _)
      mapLifted(list.asInstanceOf[LiftedList])
    }
    def copy(s: Seq[Shape[_ <: ShapeLevel, _, _, _]]) = new HListCaseClassShape(mapLifted, mapPlain) { override val shapes = s }
  }
}

Пока что,когда я пытаюсь запустить это, возникает следующая ошибка:

val q = names.zipHList(names)
val seq = Await.result(db.stream(q.result).foreach(println(_)), Duration.Inf)
println(seq)
// Exception in thread "main" java.lang.ClassCastException: scala.Tuple2 cannot be cast to slick.collection.heterogeneous.HCons
// at com.examples.HListZip$$anonfun$2.apply(HListZip.scala:57)

Кроме того, когда я просто пытаюсь получить результат, становится ясно, что на самом деле это список кортежей.

val names = TableQuery[People].map(_.name)
val q = names.zipHList(names)
val seq = Await.result(db.run(q.result), Duration.Inf)
println(seq)
// Vector((Joe,Joe), (Jack,Jack), (Jill,Jill), (John,John), (Jim,Jim)]

Что я делаю неправильно?Почему он считает, что форма - это кортеж, а не HList?

...