diff --git a/build.sbt b/build.sbt index 1eae911..0b37267 100644 --- a/build.sbt +++ b/build.sbt @@ -23,6 +23,7 @@ lazy val `slick-additions` = libraryDependencies ++= Seq( "org.scala-lang" % "scala-reflect" % scalaVersion.value % "provided", "com.typesafe.slick" %% "slick" % "3.3.2", + "com.lihaoyi" %% "sourcecode" % "0.2.1", "org.scalatest" %% "scalatest" % "3.1.1" % "test", "com.h2database" % "h2" % "1.4.200" % "test", "ch.qos.logback" % "logback-classic" % "1.2.3" % "test" diff --git a/src/main/scala/slick/additions/KeyedTableProfile.scala b/src/main/scala/slick/additions/AdditionsProfile.scala similarity index 69% rename from src/main/scala/slick/additions/KeyedTableProfile.scala rename to src/main/scala/slick/additions/AdditionsProfile.scala index 2e93d06..589a9aa 100644 --- a/src/main/scala/slick/additions/KeyedTableProfile.scala +++ b/src/main/scala/slick/additions/AdditionsProfile.scala @@ -7,11 +7,13 @@ import scala.language.{higherKinds, implicitConversions} import slick.additions.entity._ import slick.ast._ import slick.jdbc.JdbcProfile -import slick.lifted.{MappedProjection, RepShape} +import slick.lifted.{AbstractTable, ForeignKeyQuery, MappedProjection, RepShape} +import sourcecode.Name -trait KeyedTableProfile { this: JdbcProfile => - trait KeyedTableApi { this: API => + +trait AdditionsProfile { this: JdbcProfile => + trait AdditionsApi { this: API => implicit def lookupBaseColumnType[K: BaseColumnType, A]: BaseColumnType[Lookup[K, A]] = MappedColumnType.base[Lookup[K, A], K](_.key, EntityKey(_)) @@ -109,5 +111,35 @@ trait KeyedTableProfile { this: JdbcProfile => def delete(ke: KEnt)(implicit ec: ExecutionContext) = lookupQuery(ke).delete } + + trait AutoName { this: Table[_] => + def col[A: TypedType](options: ColumnOption[A]*)(implicit name: Name, dbNameStyle: NameStyle) = + column[A](dbNameStyle.identToDb(name.value), options: _*) + + def col[A: TypedType](implicit name: Name, dbNameStyle: NameStyle) = + column[A](dbNameStyle.columnName(name.value)) + + def foreign[P, PU, TT <: AbstractTable[_], U](sourceColumns: P, targetTableQuery: TableQuery[TT]) + (targetColumns: TT => P, + onUpdate: ForeignKeyAction = ForeignKeyAction.NoAction, + onDelete: ForeignKeyAction = ForeignKeyAction.NoAction) + (implicit unpackT: Shape[_ <: FlatShapeLevel, TT, U, _], + unpackP: Shape[_ <: FlatShapeLevel, P, PU, _], + name: Name, + dbNameStyle: NameStyle): ForeignKeyQuery[TT, U] = + foreignKey(dbNameStyle.foreignKeyName(tableName, name.value), sourceColumns, targetTableQuery)( + targetColumns, + onUpdate, + onDelete + ) + + def idx[A](on: A, unique: Boolean = false) + (implicit shape: Shape[_ <: FlatShapeLevel, A, _, _], name: Name, dbNameStyle: NameStyle) = + index(dbNameStyle.indexName(tableName, name.value), on, unique = unique) + } + + trait AutoNameSnakify extends AutoName { this: Table[_] => + protected implicit def nameStyle: NameStyle = NameStyle.Snakify + } } } diff --git a/src/main/scala/slick/additions/NameStyle.scala b/src/main/scala/slick/additions/NameStyle.scala new file mode 100644 index 0000000..0866032 --- /dev/null +++ b/src/main/scala/slick/additions/NameStyle.scala @@ -0,0 +1,28 @@ +package slick.additions + + +class NameStyle(val identToDb: String => String) { + def columnName(name: String): String = identToDb(name) + def foreignKeyName(tableName: String, name: String) = + tableName + "__" + identToDb(name) + def indexName(tableName: String, name: String) = + tableName + "__" + identToDb(name) +} + +object NameStyle { + private def snakify(s: String) = s.toList match { + case Nil => "" + case char :: chars => + chars + .foldLeft(char :: Nil) { + case (x :: xs, c) if x.isLower && c.isUpper => + c.toLower :: '_' :: x :: xs + case (xs, c) => + c :: xs + } + .reverse + .mkString + } + val Exact = new NameStyle(identity) + val Snakify = new NameStyle(snakify) +} diff --git a/src/test/scala/slick/additions/test/TestProfile.scala b/src/test/scala/slick/additions/test/TestProfile.scala index 9c0f63c..e9543ba 100644 --- a/src/test/scala/slick/additions/test/TestProfile.scala +++ b/src/test/scala/slick/additions/test/TestProfile.scala @@ -1,11 +1,11 @@ package slick.additions.test -import slick.additions.KeyedTableProfile +import slick.additions.AdditionsProfile import slick.jdbc.H2Profile -trait TestProfile extends H2Profile with KeyedTableProfile { - object _api extends KeyedTableApi with API +trait TestProfile extends H2Profile with AdditionsProfile { + object _api extends AdditionsApi with API override val api = _api }