aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStewart Stewart <stewinsalot@gmail.com>2016-09-15 15:08:41 -0700
committerGitHub <noreply@github.com>2016-09-15 15:08:41 -0700
commit2192d4b67b1bcc7b5222e1d44f00f30ec16bce28 (patch)
treea05a7b5b3fbc1c577538df3d1f8e13bf091c4e60
parenta2129b5b2e5284a24d3e3681cb516cc2ec9beded (diff)
parent44a77eae23c3e159d08e7a025e0c5759ffa0f4ba (diff)
downloadslick-codegen-plugin-2192d4b67b1bcc7b5222e1d44f00f30ec16bce28.tar.gz
slick-codegen-plugin-2192d4b67b1bcc7b5222e1d44f00f30ec16bce28.tar.bz2
slick-codegen-plugin-2192d4b67b1bcc7b5222e1d44f00f30ec16bce28.zip
Merge pull request #3 from drivergroup/use-driver-core-ids-time
Use Id and Time from driver-core
-rw-r--r--src/main/scala/NamespacedCodegen.scala124
1 files changed, 51 insertions, 73 deletions
diff --git a/src/main/scala/NamespacedCodegen.scala b/src/main/scala/NamespacedCodegen.scala
index bdda76a..44826fe 100644
--- a/src/main/scala/NamespacedCodegen.scala
+++ b/src/main/scala/NamespacedCodegen.scala
@@ -1,18 +1,20 @@
-import slick.dbio.{NoStream, DBIOAction}
+import java.io.{FileWriter, File}
+import java.net.URI
import scala.concurrent.Await
+import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.reflect.runtime.currentMirror
+
import slick.ast.ColumnOption
+import slick.backend.DatabaseConfig
+import slick.codegen.{AbstractGenerator, SourceCodeGenerator}
+import slick.dbio.{DBIO, DBIOAction, NoStream}
import slick.driver.JdbcProfile
import slick.jdbc.meta.MTable
-import slick.codegen.{AbstractGenerator, SourceCodeGenerator}
-import slick.model._
import slick.{model => m}
-import scala.concurrent.ExecutionContext.Implicits.global
-
-import java.io.File
-import java.io.FileWriter
+import slick.model.{Column, Model, Table}
+import slick.util.ConfigExtensionMethods.configExtensionMethods
// NamespacedCodegen handles tables within schemas by namespacing them
// within objects here
@@ -20,24 +22,17 @@ import java.io.FileWriter
// generator places the relevant generated classes into separate
// objects--a "a" object, and a "b" object)
object NamespacedCodegen {
- def parseSchemaList(schemaTableNames: List[String]): Map[String, List[String]] = {
- val (tables, schemas) = schemaTableNames.partition(_.contains("."))
- val mappedSchemas = schemas.map(_ -> List()).toMap
- val mappedTables = tables.groupBy(_.split("\\.")(0)).map {
- case (key, value) => (key, value.map(_.split("\\.")(1)).asInstanceOf[List[String]])
- }
-
- mappedSchemas ++ mappedTables
- }
-
- import slick.dbio.DBIO
- import slick.model.Model
+ def parseSchemaList(schemaTableNames: List[String]): Map[String, List[String]] =
+ schemaTableNames.map(_.split('.'))
+ .groupBy(_.head)
+ .mapValues(_.flatMap(_.tail))
+ .toMap
def createFilteredModel(driver: JdbcProfile, mappedSchemas: Map[String, List[String]]): DBIO[Model] =
driver.createModel(Some(
- MTable.getTables.map(_.filter((t: MTable) => mappedSchemas
- .get(t.name.schema.getOrElse(""))
- .fold(false)(ts => ts.isEmpty || ts.contains(t.name.name))))))
+ MTable.getTables.map(_.filter((t: MTable) =>
+ t.name.schema.flatMap(mappedSchemas.get).exists(tables =>
+ tables.isEmpty || tables.contains(t.name.name))))))
def references(dbModel: Model, tcMappings: Map[(String, String), (String, String)]): Map[(String, String), (Table, Column)] = {
def getTableColumn(tc: (String, String)) : (Table, Column) = {
@@ -52,11 +47,6 @@ object NamespacedCodegen {
tcMappings.map{case (from, to) => ({getTableColumn(from); from}, getTableColumn(to))}
}
-
- import java.net.URI
- import slick.backend.DatabaseConfig
- import slick.util.ConfigExtensionMethods.configExtensionMethods
-
def run(
uri: URI,
pkg: String,
@@ -74,18 +64,21 @@ object NamespacedCodegen {
val manualReferences = references(dbModel, manualForeignKeys)
def codegen(typeFile: Boolean) = new SourceCodeGenerator(dbModel){
- def derefColumn(table: m.Table, column: m.Column): (m.Table, m.Column) =
- (table.foreignKeys.toList
- .filter(_.referencingColumns.forall(_ == column))
- .flatMap(fk =>
- fk.referencedColumns match {
- case Seq(c) => dbModel.tablesByName.get(fk.referencedTable).map{(_, c)}
- case _ => None
- }) ++
- manualReferences.get((table.name.asString, column.name)))
- .headOption
+
+ def derefColumn(table: m.Table, column: m.Column): (m.Table, m.Column) = {
+ val referencedColumn: Seq[(m.Table, m.Column)] = table.foreignKeys
+ .filter(tableFk => tableFk.referencingColumns.forall(_ == column))
+ .filter(columnFk => columnFk.referencedColumns.length == 1)
+ .flatMap(_.referencedColumns
+ .map(c => (dbModel.tablesByName(c.table), c)))
+
+ assert(referencedColumn.distinct.length <= 1, referencedColumn)
+
+ referencedColumn.headOption
+ .orElse(manualReferences.get((table.name.asString, column.name)))
.map((derefColumn _).tupled)
.getOrElse((table, column))
+ }
// Is this compatible with ***REMOVED*** Id? How do we make it generic?
def idType(t: m.Table) : String =
@@ -97,14 +90,13 @@ object NamespacedCodegen {
// Why can't we simply re-use?
var imports =
- // acyclic is unnecessary in generic projects
- //if (typeFile) "import acyclic.file\nimport dbmodels.rows\n"
- //else
"import slick.model.ForeignKeyAction\n" +
- "import rows._\n" +
+ "import dbmodels.rows\n" +
( if(tables.exists(_.hlistEnabled)){
- "import slick.collection.heterogeneous._\n"+
- "import slick.collection.heterogeneous.syntax._\n"
+ "import slick.collection.heterogeneous._\n" +
+ "import slick.collection.heterogeneous.syntax._\n" +
+ "import com.drivergrp.core._\n" +
+ "import com.drivergrp.core.database._\n"
} else ""
) +
( if(tables.exists(_.PlainSqlMapper.enabled)){
@@ -113,35 +105,22 @@ object NamespacedCodegen {
} else ""
) + "\n\n" // We didn't copy ddl though
+ val sortedSchemaTables: List[(String, Seq[TableDef])] = tables
+ .groupBy(t => t.model.name.schema.getOrElse("`public`"))
+ .toList.sortBy(_._1)
- val bySchema = tables.groupBy(t => {
- t.model.name.schema
- })
+ val schemata: String = sortedSchemaTables.map {
+ case (schemaName, tables) =>
+ val tableCode = tables
+ .sortBy(_.model.name.table)
+ .map(_.code.mkString("\n"))
+ .mkString("\n\n")
+ indent(s"object $schemaName extends CoreDBMappers {\n$tableCode")+"\n}\n"
+ }.mkString("\n\n")
- val schemaFor = (schema: String) => {
- bySchema(Option(schema)).sortBy(_.model.name.table).map(
- _.code.mkString("\n") // TODO explore here
- ).mkString("\n\n")
- }
+ val mapperTrait: String = """trait CoreDBMappers extends com.drivergrp.core.database.IdColumnTypes { override val database = com.drivergrp.core.database.Database.fromConfig("slick.db.default") }"""
- val schemata = mappedSchemas.keys.toList.sorted.map(
- s => indent("object" + " " + s + " {\n" + schemaFor(s)) + "\n}\n"
- ).mkString("\n\n")
-
- val idType =
- if (typeFile)// Should not be defined here.
- """|case class Id[T](v: Int)
- |""".stripMargin
- else
- // This should be in a separate Implicits trait
- """|implicit def idTypeMapper[A] : BaseColumnType[Id[A]] =
- | MappedColumnType.base[Id[A], Int](_.v, Id(_))
- |import play.api.mvc.PathBindable
- |implicit def idPathBindable[A] : PathBindable[Id[A]] = implicitly[PathBindable[Int]].transform[Id[A]](Id(_),_.v)
- |""".stripMargin
- //pathbindable is play specific
- // Id works only with labdash Id
- imports + idType + schemata
+ imports + mapperTrait + "\n\n" + schemata
}
// This is overridden to output classfiles elsewhere
@@ -239,9 +218,8 @@ object NamespacedCodegen {
else model.tpe match {
// how does this type work out?
// There should be a way to add adhoc custom time mappings
- case "java.sql.Date" => "tools.Date"
- case "java.sql.Time" => "tools.Time"
- case "java.sql.Timestamp" => "tools.Time"
+ case "java.sql.Time" => "com.drivergrp.core.time.Time"
+ case "java.sql.Timestamp" => "com.drivergrp.core.time.Time"
case _ => super.rawType
}
}
@@ -255,7 +233,7 @@ object NamespacedCodegen {
fw.write(c)
fw.close()
}
- val disableScalariform = "filename/ format: OFF\n"
+ val disableScalariform = "// filename/ format: OFF\n"
val tablesSource = codegen(false).packageCode(slickDriver, pkg, "Tables", None)
val rowsSource = s"package $pkg.rows\n\n" + codegen(true).code