Skip to content

Instantly share code, notes, and snippets.

@neowit
Created April 15, 2016 16:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neowit/44d1ce3a2dac2eb7d8bf202655a199db to your computer and use it in GitHub Desktop.
Save neowit/44d1ce3a2dac2eb7d8bf202655a199db to your computer and use it in GitHub Desktop.
Slick codegen - wrapper class for tables with > 22 columns to simplify accessing fields in query results
/**
*
* this is a simple customisation for Slick Codegen which automatically
* generates wrapper class with field accessors for tables with more than 22
* fields.
* Wrapper allows more convenient access to record fields returned from query
*
* class ContactWrapper(private val row: ContactRow) {
// addressing HList by index is very slow, let's convert it to vector
private lazy val values = row.toList.toVector
lazy val birthdate: Option[java.time.LocalDate] = values(0).asInstanceOf[Option[java.time.LocalDate]]
lazy val phone: Option[String] = values(1).asInstanceOf[Option[String]]
lazy val mailingpostalcode: Option[Strin2] = values(5).asInstanceOf[Option[String]]
lazy val email: Option[String] = values(3).asInstanceOf[Option[String]]
...
}
// usage example
val contactOpt: Future[Option[ContactWrapper]] = db.run(query.result.headOption).map(contactRowOpt => contactRowOpt.map(new ContactWrapper(_)) )
*/
class MyCodegenCustomisations(model: Model) extends slick.codegen.SourceCodeGenerator(model){
import ColumnDetection._
override def Table = new Table(_){
table =>
val columnIndexByName = columns.map(_.name).zipWithIndex.toMap
def getColumnIndex(columnName: String): Option[Int] = {
columnIndexByName.get(columnName)
}
private def getWrapperCode: Seq[String] = {
if (columns.length <= 22) {
//do not generate wrapper for tables which get case class generated by Slick
Seq.empty[String]
} else {
val nonHerokuColumns = columns.filterNot(_.name.startsWith("_"))
val lines =
nonHerokuColumns.map{c =>
getColumnIndex(c.name) match {
case Some(colIndex) =>
//lazy val firstname: Option[String] = row.productElement(1).asInstanceOf[Option[String]]
val colType = c.exposedType
val line = s"lazy val ${c.name}: $colType = values($colIndex).asInstanceOf[$colType]"
line
case None => ""
}
}
Seq("",
"/*",
"case class Wrapper(private val row: Row) {",
"// addressing HList by index is very slow, let's convert it to vector",
"private lazy val values = row.toList.toVector",
""
) ++ lines ++ Seq("}", "*/", "")
}
}
override def code: Seq[String] = {
val originalCode = super.code
originalCode ++ this.getWrapperCode
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment