case class MyTableElem(id: Long, created: DateTime, ...) // contains more than 22 fields
class MyTable(tag: Tag) extends Table[MyTableElem](tag, "my_table") {
def id = column[Long]("id")
def created = column[Long]("created")
...
lazy val hlist = (id :: created :: ... :: HNil)
def * = hlist.shaped <> (MyTableElem(...), {el: MyTableElm => Option((el.id, el.created, ...))})
}
object DbTables {
val myTable = TableQuery[MyTable]
}
case class SortingRequest(rep: Rep[_], direction: slick.ast.Ordering)
// store column names.
val myTableColumns = DbTables.myTable.baseTableRow.create_*.map(_.name).toList
def mapSortToRequest(s: Option[String]): MyTable => SortingRequest = { myTable =>
val (sort, direction) = s.map(str => str.toList match {
case prefix :: tail if prefix == '-' => (tail.mkString(""), slick.ast.Ordering(slick.ast.Ordering.Asc))
case prefix :: tail => (str, slick.ast.Ordering(slick.ast.Ordering.Desc))
case Nil => ("created", slick.ast.Ordering(slick.ast.Ordering.Desc)) // default to created.
}).getOrElse(("created", slick.ast.Ordering(slick.ast.Ordering.Desc)))
val myTableReps = myTable.hlist.toList
val mapping = myTableReps.foldLeft((0, Map.empty[String, slick.lifted.Rep[_]])) {
case (((index, accumulator), next)) =>
(index + 1, accumulator + ((myTableColumns(index), next.asInstanceOf[slick.lifted.Rep[_]])))
}._2
mapping.find(s => s._1 == sort) match {
case Some((_, rep)) => SortingRequest(rep, direction)
case None => throw new Exception("sort")
}
}
class PgDynamicSortable[TB <: Table[EL], EL, EX[_]](q: Query[TB, EL, EX]) {
private def generateOrdFromRep: SortingRequest => slick.lifted.Ordered = {
t => new slick.lifted.Ordered(Vector((t.rep.toNode, t.direction)))
}
def dynamicSort(f: TB => (SortingRequest)): Query[TB, EL, EX] = {
q.sortBy(e => f(e))(generateOrdFromRep)
}
}
val myTableColumns = DbTables. myTable.baseTableRow.create_*.map(_.name).toList
val myTableReps = DbTables. myTable.baseTableRow.hlist.toList
val mapping = myTableReps.foldLeft((0, Map.empty[String, slick.lifted.Rep[_]])) {
case (((index, accumulator), next)) =>
(index + 1, accumulator + ((myTableColumns(index), next.asInstanceOf[slick.lifted.Rep[_]])))
}._2// if this would work I could remove the need for the myTable variable
def mapSortToRequest(s: Option[String]): MyTable => SortingRequest = { myTable =>
val (sort, direction) = s.map(str => str.toList match {
case prefix :: tail if prefix == '-' => (tail.mkString(""), slick.ast.Ordering(slick.ast.Ordering.Asc))
case prefix :: tail => (str, slick.ast.Ordering(slick.ast.Ordering.Desc))
case Nil => ("created", slick.ast.Ordering(slick.ast.Ordering.Desc)) // default to created.
}).getOrElse(("created", slick.ast.Ordering(slick.ast.Ordering.Desc)))
mapping.find(s => s._1 == sort) match {
case Some((_, rep)) => SortingRequest(rep, direction)
case None => throw new Exception("sort")
}
}
slick.SlickException: No type for symbol i_id found in Vector[t2<@t3<UnassignedType>>]
at slick.ast.Type$class.select(Type.scala:24)
at slick.ast.CollectionType.select(Type.scala:132)
at slick.ast.Select.buildType(Node.scala:530)
at slick.ast.SimplyTypedNode$class.withInferredType(Node.scala:124)
at slick.ast.Select.withInferredType(Node.scala:520)
at slick.ast.Select.withInferredType(Node.scala:520)
at slick.ast.Node$class.infer(Node.scala:90)
at slick.ast.Select.infer(Node.scala:520)
at slick.ast.ComplexFilteredQuery$$anonfun$4.apply(Node.scala:304)
at slick.ast.ComplexFilteredQuery$$anonfun$4.apply(Node.scala:303)
Map(id -> mytableelem.id, created -> mytableelm, ...)
Map(id-> (mytablelem Ref @1356960571).id, created -> (mytablelem Ref @1356960571).created, ...)