Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Slick code generator to include database views as well?

I'm trying to generate the Scala code for the database tables and views in my schema using Slick 3.0.3. Taking this blog as example I have the following file build.sbt. However, this will generate code for my database tables and will not include the database views. How can I get the views generated as well?

According to slick issue 1022 I see it is possible to do but the API doesn't look alike and slick.codegen.SourceCodeGenerator doesn't have a getTables or defaultTables to include view names.

name := "slickCodeGen"

version := "1.0"

scalaVersion := "2.11.6"

scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")

libraryDependencies ++= Seq(
  "com.typesafe.slick" %% "slick" % "3.0.3",
  "com.typesafe.slick" %% "slick-codegen" % "3.0.3",
  "org.postgresql" %  "postgresql" % "9.4-1201-jdbc41",
  "com.zaxxer" % "HikariCP" % "2.3.2",
  "org.scalatest" %% "scalatest" % "2.2.4" % "test"
)

slick <<= slickCodeGenTask

sourceGenerators in Compile <+= slickCodeGenTask

lazy val slick = TaskKey[Seq[File]]("gen-tables")
lazy val slickCodeGenTask = (sourceManaged, dependencyClasspath in Compile, runner in Compile, streams) map { (dir, cp, r, s) =>
  val outputDir = (dir / "main/slick").getPath
  val username = "postgres"
  val password = "xxx"
  val url = "jdbc:postgresql://localhost:5555/testdb?searchpath=public"
  val jdbcDriver = "com.postgresql.jdbc.Driver"
  val slickDriver = "slick.driver.PostgresDriver"
  val pkg = "folder1.folder2"
  toError(r.run("slick.codegen.SourceCodeGenerator", cp.files, Array(slickDriver, jdbcDriver, url, outputDir, pkg, username, password), s.log))
  val fname = outputDir + "/folder1/folder2/" + "Tables.scala"
  Seq(file(fname))
}
like image 225
SkyWalker Avatar asked Sep 24 '15 08:09

SkyWalker


1 Answers

After a lot of trial and error due to the many changes in the Slick generator API the following standalone application Generator.scala tested will generate the code for both tables and views under Slick 3.0.3:

import java.util.concurrent.TimeUnit

import slick.driver.PostgresDriver
import slick.jdbc.meta.MTable
import slick.codegen.SourceCodeGenerator
import slick.driver.PostgresDriver.simple._
import play.api.libs.concurrent.Execution.Implicits._

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}

object Generator extends App {
  val slickDriver = "slick.driver.PostgresDriver"
  val jdbcDriver = "org.postgresql.Driver"
  val url = "jdbc:postgresql://localhost:5555/testdb?searchpath=public"
  val outputDir = "/tmp/"
  val pkg = "folder1.folder2"
  val username = "postgres"
  val password = "xxx"

  val db = Database.forURL(url, user, password)
  val dbio = PostgresDriver.createModel(Some(MTable.getTables(None, None, None, Some(Seq("TABLE", "VIEW")))))
  val model = db.run(dbio)
  val future : Future[SourceCodeGenerator] = model.map(model => new SourceCodeGenerator(model))
  val codegen : SourceCodeGenerator = Await.result(future, Duration.create(5, TimeUnit.MINUTES))
  codegen.writeToFile(slickDriver, outputDir, pkg, "Tables", "Tables.scala")
}

Integrating this code into a build.sbt is not that easy because requires defining an external custom code generator file and then compiling and running it from the build.sbt before the actual project is compiled. A very outdated example of this can be found in the github project slick-codegen-customization-example but note that they don't have a build.sbt but a more advanced Build.scala

like image 189
SkyWalker Avatar answered Nov 15 '22 07:11

SkyWalker