diff options
author | Stewart Stewart <stewinsalot@gmail.com> | 2017-02-28 10:33:46 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-28 10:33:46 -0800 |
commit | 85f038499e98cc9df92a3912ea3b3ac48990c82e (patch) | |
tree | 4381cfb76e120bc505616ad8e415311cfbcaa2e0 /src/main/scala/TypedIdTable.scala | |
parent | 4433116ef5c57e0970e6d1a668dfc189ffe96cba (diff) | |
parent | 324bed11590c480d87a34ff5452e038c2a265b07 (diff) | |
download | slick-codegen-plugin-85f038499e98cc9df92a3912ea3b3ac48990c82e.tar.gz slick-codegen-plugin-85f038499e98cc9df92a3912ea3b3ac48990c82e.tar.bz2 slick-codegen-plugin-85f038499e98cc9df92a3912ea3b3ac48990c82e.zip |
Merge pull request #26 from drivergroup/underlying-id
Generate implicits per column using underlying type
Diffstat (limited to 'src/main/scala/TypedIdTable.scala')
-rw-r--r-- | src/main/scala/TypedIdTable.scala | 93 |
1 files changed, 66 insertions, 27 deletions
diff --git a/src/main/scala/TypedIdTable.scala b/src/main/scala/TypedIdTable.scala index 1a8f986..2e58cd5 100644 --- a/src/main/scala/TypedIdTable.scala +++ b/src/main/scala/TypedIdTable.scala @@ -10,40 +10,79 @@ class TypedIdSourceCodeGenerator( val manualReferences = SchemaParser.references(databaseModel, manualForeignKeys) - 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 => - (databaseModel.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)) + val modelTypeToColumnMaper = Map( + "java.util.UUID" -> "uuidKeyMapper", + "String" -> "naturalKeyMapper", + "Int" -> "serialKeyMapper" + ) + + val keyReferences: Map[m.Column, m.Column] = { + val pks = databaseModel.tables + .flatMap(_.columns) + .filter(_.options.contains(slick.ast.ColumnOption.PrimaryKey)) + .map(c => (c -> c)) + + val fks: Seq[(m.Column, m.Column)] = databaseModel.tables + .flatMap(_.foreignKeys) + .filter(_.referencedColumns.length == 1) + .filter(_.referencedColumns.forall( + _.options.contains(slick.ast.ColumnOption.PrimaryKey))) + .flatMap(fk => + fk.referencingColumns.flatMap(from => + fk.referencedColumns.headOption.map(to => (from -> to)))) + + (pks ++ fks).toMap + } + + def pKeyTypeTag(columnRef: m.Column): String = { + val schemaName = columnRef.table.schema.getOrElse("`public`") + val tableName = entityName(columnRef.table.table) + s"$schemaName.$tableName" + } + + def pKeyType(columnRef: m.Column): String = { + s"${idType.getOrElse("Id")}[${pKeyTypeTag(columnRef)}]" } class TypedIdTable(model: m.Table) extends Table(model) { table => + override def definitions = + Seq[Def](EntityType, + PlainSqlMapper, + TableClass, + TableValue, + PrimaryKeyMapper) + class TypedIdColumn(override val model: m.Column) extends Column(model) { - column => + override def rawType: String = { + keyReferences.get(model).fold(super.rawType)(pKeyType) + } + } + + type PrimaryKeyMapper = PrimaryKeyMapperDef + + def PrimaryKeyMapper = new PrimaryKeyMapper {} - def tableReferenceName(tableName: m.QualifiedName) = { - val schemaObjectName = tableName.schema.getOrElse("`public`") - val rowTypeName = entityName(tableName.table) - val idTypeName = idType.getOrElse("Id") - s"$idTypeName[$schemaObjectName.$rowTypeName]" + class PrimaryKeyMapperDef extends TermDef { + def primaryKeyColumn: Option[Column] = { + table.model.columns + .flatMap(c => keyReferences.get(c).filter(_ == c)) + .headOption + .map(c => table.columnsByName(c.name)) } - override def rawType: String = { - // write key columns as Id types - val (referencedTable, referencedColumn) = - derefColumn(table.model, column.model) - if (referencedColumn.options.contains( - slick.ast.ColumnOption.PrimaryKey)) - tableReferenceName(referencedTable.name) - else super.rawType + override def enabled = primaryKeyColumn.isDefined + + override def doc = + s"Implicit for mapping primary key of ${tableName(table.model.name.table)} to a base column" + + override def rawName = tableName(table.model.name.table) + "KeyMapper" + + override def code = primaryKeyColumn.fold("") { column => + val tpe = s"BaseColumnType[${column.rawType}]" + s"""|implicit def $name: $tpe = + |${modelTypeToColumnMaper(column.model.tpe)}[${pKeyTypeTag( + column.model)}] + |""".stripMargin.lines.mkString("").trim } } } |