Created
April 15, 2016 16:25
-
-
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 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
/** | |
* | |
* 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