Created
November 20, 2016 16:21
-
-
Save deusaquilus/5b52b82598c534ca09119efcf0acbc50 to your computer and use it in GitHub Desktop.
Creating a CaseClassShape that uses HList therefore can have >22 Arity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object CaseClassHListShapeQueryExample { | |
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 } | |
} | |
type DirectConsList = HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HCons[String, HNil]]]]]]]]]]]]]]]]]]]]]]]]] | |
type LiftedConsList = HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HNil]]]]]]]]]]]]]]]]]]]]]]]]] | |
implicit def toDirect(list:DirectConsList) = { | |
list match { | |
case data1 :: data2 :: data3 :: data4 :: data5 :: data6 :: data7 :: data8 :: data9 :: data10 :: data11 :: data12 :: data13 :: data14 :: data15 :: data16 :: data17 :: data18 :: data19 :: data20 :: data21 :: data22 :: data23 :: data24 :: data25 :: HNil => { | |
B(data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, data24, data25 ) | |
} | |
case _ => throw new Exception("malformed HList") | |
} | |
} | |
def toLifted(list:HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HCons[Rep[String], HNil]]]]]]]]]]]]]]]]]]]]]]]]]) = { | |
list match { | |
case data1 :: data2 :: data3 :: data4 :: data5 :: data6 :: data7 :: data8 :: data9 :: data10 :: data11 :: data12 :: data13 :: data14 :: data15 :: data16 :: data17 :: data18 :: data19 :: data20 :: data21 :: data22 :: data23 :: data24 :: data25 :: HNil => { | |
LiftedB(data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, data24, data25 ) | |
} | |
case _ => throw new Exception("malformed HList") | |
} | |
} | |
implicit object BShape extends HListCaseClassShape[ | |
Product, | |
LiftedConsList, | |
LiftedB, | |
DirectConsList, | |
B](toLifted, toDirect) | |
case class LiftedB(data1: Rep[String], data2: Rep[String], data3: Rep[String], data4: Rep[String], data5: Rep[String], data6: Rep[String], data7: Rep[String], data8: Rep[String], data9: Rep[String], data10: Rep[String], data11: Rep[String], data12: Rep[String], data13: Rep[String], data14: Rep[String], data15: Rep[String], data16: Rep[String], data17: Rep[String], data18: Rep[String], data19: Rep[String], data20: Rep[String], data21: Rep[String], data22: Rep[String], data23: Rep[String], data24: Rep[String], data25: Rep[String]) | |
case class B(data1: String, data2: String, data3: String, data4: String, data5: String, data6: String, data7: String, data8: String, data9: String, data10: String, data11: String, data12: String, data13: String, data14: String, data15: String, data16: String, data17: String, data18: String, data19: String, data20: String, data21: String, data22: String, data23: String, data24: String, data25: String ) | |
def main(args:Array[String]) { | |
val queryAll = for { | |
f <- TableQuery[Users] | |
} yield LiftedB(f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind), f.name.getOrElse("".bind)) | |
val db = SomeDriver.api.Database.forURL( | |
url = "jdbc:...", | |
driver = "...", | |
user = user, | |
password = password) | |
val res = db.stream(query.result).foreach(println(_)) | |
Await.result(res, Duration.Inf) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The regular i.e. 'monomorphic' Slick CaseClassShape maps back and fourth via tuples which are still affected (as of slick 3.1.1 / Scala 2.11) by the 22 arity limitation. That is to say, if you want to create a CaseClassShape with more then 22 fields your are out of luck with out-of-the-box Slick. Fortunately using Stephan Zeiger's HListShape (info here) I have managed to create a HListCaseClassShape that overcomes the 22 arity limit by mapping to HLists instead of tuples (original posting here) which should work exactly the same way in most cases.