3

For my own (mostly didactic - understanding the black magic behind slick and the reflection API of scala) purposes, I'd like to create a function that would be able to create a table if it is missing from the database, with an API such as this:

class Raws(tag: Tag) extends Table[Raw](tag, "raw") {
  def id = column[Int]("ID", O.PrimaryKey)
  def subject = column[String]("subject")
  def xml = column[String]("xml")

  def * = (id.?, subject, xml) <> ((Raw.apply _).tupled, Raw.unapply)
}

createTable[Raws](database)

My attempt is this:

  def createTable[T <: Table[R], R](dat: Database)(implicit session: Session, tag: TypeTag[T], tag2: TypeTag[R]) = {

    val q = TableQuery[T]

    dat.run(MTable.getTables(q.baseTableRow.tableName)).map { tables =>
      if (tables.toList.isEmpty) {
        q2.schema.create
        q.schema.create
      }
    }
  }

Which, I guess should run, but produces the following output (scala 2.11.7):

compile

[error] /Users/avandra/projects/freelancer/dmarcreport/src/main/scala/DMarcReportReader.scala:76: class type required but T found
[error]     val q2 = TableQuery[T]
[error]                        ^
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 1 s, completed Sep 14, 2015 3:18:19 PM

Turning on the macro debug:

[info] Compiling 3 Scala sources to /scalaproject/target/scala-2.11/classes...
performing macro expansion scala.slick.`package`.driver.PostgresDriver.simple.TableQuery.apply[T] at source-/scalaproject/src/main/scala/DMarcReportReader.scala,line-75,offset=2090
TableQuery.apply[T](((tag: Tag) => new T(tag)))
Apply(TypeApply(Select(Ident(slick.lifted.TableQuery), TermName("apply")), List(TypeTree())), List(Function(List(ValDef(Modifiers(PARAM), TermName("tag"), Ident(slick.lifted.Tag), EmptyTree)), Apply(Select(New(TypeTree()), termNames.CONSTRUCTOR), List(Ident(TermName("tag")))))))
[error] /scalaproject/src/main/scala/DMarcReportReader.scala:75: class type required but T found
[error]     val q2 = TableQuery[T]
[error]                        ^
performing macro expansion `package`.this.materializeTypeTag[db.Raws](scala.reflect.runtime.`package`.universe) at source-/scalaproject/src/main/scala/DMarcReportReader.scala,line-119,offset=3802
{
  val $u: reflect.runtime.universe.type = scala.reflect.runtime.`package`.universe;
  val $m: $u.Mirror = scala.reflect.runtime.`package`.universe.runtimeMirror(this.getClass().getClassLoader());
  $u.TypeTag.apply[db.Raws]($m, {
    final class $typecreator1 extends TypeCreator {
      def <init>(): $typecreator1 = {
        $typecreator1.super.<init>();
        ()
      };
      def apply[U <: scala.reflect.api.Universe with Singleton]($m$untyped: scala.reflect.api.Mirror[U]): U#Type = {
        val $u: U = $m$untyped.universe;
        val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
        $m.staticClass("db.Raws").asType.toTypeConstructor
      }
    };
    new $typecreator1()
  })
}
Block(List(ValDef(Modifiers(), TermName("$u"), TypeTree().setOriginal(SingletonTypeTree(Select(Select(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), scala.reflect.runtime.package), TermName("universe")))), Select(Select(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), scala.reflect.runtime.package), TermName("universe"))), ValDef(Modifiers(), TermName("$m"), TypeTree().setOriginal(Select(Ident(TermName("$u")), TypeName("Mirror"))), Apply(Select(Select(Select(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), scala.reflect.runtime.package), TermName("universe")), TermName("runtimeMirror")), List(Apply(Select(Apply(Select(This(TypeName("DMarcReportReader")), TermName("getClass")), List()), TermName("getClassLoader")), List()))))), Apply(TypeApply(Select(Select(Ident(TermName("$u")), TermName("TypeTag")), TermName("apply")), List(TypeTree())), List(Ident(TermName("$m")), Block(List(ClassDef(Modifiers(FINAL), TypeName("$typecreator1"), List(), Template(List(Ident(scala.reflect.api.TypeCreator)), noSelfType, List(DefDef(Modifiers(), termNames.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(TypeName("$typecreator1")), typeNames.EMPTY), termNames.CONSTRUCTOR), List())), Literal(Constant(())))), DefDef(Modifiers(), TermName("apply"), List(TypeDef(Modifiers(PARAM), TypeName("U"), List(), TypeTree().setOriginal(TypeBoundsTree(TypeTree().setOriginal(Ident(scala.Nothing)), TypeTree().setOriginal(CompoundTypeTree(Template(List(Ident(scala.reflect.api.Universe), Ident(scala.Singleton)), noSelfType, List()))))))), List(List(ValDef(Modifiers(PARAM), TermName("$m$untyped"), TypeTree().setOriginal(AppliedTypeTree(Ident(scala.reflect.api.Mirror), List(TypeTree().setOriginal(Ident(TypeName("U")))))), EmptyTree))), TypeTree().setOriginal(SelectFromTypeTree(TypeTree().setOriginal(Ident(TypeName("U"))), TypeName("Type"))), Block(List(ValDef(Modifiers(), TermName("$u"), TypeTree().setOriginal(Ident(TypeName("U"))), Select(Ident(TermName("$m$untyped")), TermName("universe"))), ValDef(Modifiers(), TermName("$m"), TypeTree().setOriginal(Select(Ident(TermName("$u")), TypeName("Mirror"))), TypeApply(Select(Ident(TermName("$m$untyped")), TermName("asInstanceOf")), List(TypeTree().setOriginal(Select(Ident(TermName("$u")), TypeName("Mirror"))))))), Select(Select(Apply(Select(Ident(TermName("$m")), TermName("staticClass")), List(Literal(Constant("db.Raws")))), TermName("asType")), TermName("toTypeConstructor")))))))), Apply(Select(New(Ident(TypeName("$typecreator1"))), termNames.CONSTRUCTOR), List())))))
performing macro expansion `package`.this.materializeTypeTag[db.Raw](scala.reflect.runtime.`package`.universe) at source-/scalaproject/src/main/scala/DMarcReportReader.scala,line-119,offset=3802
{
  val $u: reflect.runtime.universe.type = scala.reflect.runtime.`package`.universe;
  val $m: $u.Mirror = scala.reflect.runtime.`package`.universe.runtimeMirror(this.getClass().getClassLoader());
  $u.TypeTag.apply[db.Raw]($m, {
    final class $typecreator2 extends TypeCreator {
      def <init>(): $typecreator2 = {
        $typecreator2.super.<init>();
        ()
      };
      def apply[U <: scala.reflect.api.Universe with Singleton]($m$untyped: scala.reflect.api.Mirror[U]): U#Type = {
        val $u: U = $m$untyped.universe;
        val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror];
        $m.staticClass("db.Raw").asType.toTypeConstructor
      }
    };
    new $typecreator2()
  })
}
Block(List(ValDef(Modifiers(), TermName("$u"), TypeTree().setOriginal(SingletonTypeTree(Select(Select(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), scala.reflect.runtime.package), TermName("universe")))), Select(Select(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), scala.reflect.runtime.package), TermName("universe"))), ValDef(Modifiers(), TermName("$m"), TypeTree().setOriginal(Select(Ident(TermName("$u")), TypeName("Mirror"))), Apply(Select(Select(Select(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), scala.reflect.runtime.package), TermName("universe")), TermName("runtimeMirror")), List(Apply(Select(Apply(Select(This(TypeName("DMarcReportReader")), TermName("getClass")), List()), TermName("getClassLoader")), List()))))), Apply(TypeApply(Select(Select(Ident(TermName("$u")), TermName("TypeTag")), TermName("apply")), List(TypeTree())), List(Ident(TermName("$m")), Block(List(ClassDef(Modifiers(FINAL), TypeName("$typecreator2"), List(), Template(List(Ident(scala.reflect.api.TypeCreator)), noSelfType, List(DefDef(Modifiers(), termNames.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(TypeName("$typecreator2")), typeNames.EMPTY), termNames.CONSTRUCTOR), List())), Literal(Constant(())))), DefDef(Modifiers(), TermName("apply"), List(TypeDef(Modifiers(PARAM), TypeName("U"), List(), TypeTree().setOriginal(TypeBoundsTree(TypeTree().setOriginal(Ident(scala.Nothing)), TypeTree().setOriginal(CompoundTypeTree(Template(List(Ident(scala.reflect.api.Universe), Ident(scala.Singleton)), noSelfType, List()))))))), List(List(ValDef(Modifiers(PARAM), TermName("$m$untyped"), TypeTree().setOriginal(AppliedTypeTree(Ident(scala.reflect.api.Mirror), List(TypeTree().setOriginal(Ident(TypeName("U")))))), EmptyTree))), TypeTree().setOriginal(SelectFromTypeTree(TypeTree().setOriginal(Ident(TypeName("U"))), TypeName("Type"))), Block(List(ValDef(Modifiers(), TermName("$u"), TypeTree().setOriginal(Ident(TypeName("U"))), Select(Ident(TermName("$m$untyped")), TermName("universe"))), ValDef(Modifiers(), TermName("$m"), TypeTree().setOriginal(Select(Ident(TermName("$u")), TypeName("Mirror"))), TypeApply(Select(Ident(TermName("$m$untyped")), TermName("asInstanceOf")), List(TypeTree().setOriginal(Select(Ident(TermName("$u")), TypeName("Mirror"))))))), Select(Select(Apply(Select(Ident(TermName("$m")), TermName("staticClass")), List(Literal(Constant("db.Raw")))), TermName("asType")), TermName("toTypeConstructor")))))))), Apply(Select(New(Ident(TypeName("$typecreator2"))), termNames.CONSTRUCTOR), List())))))
performing macro expansion slick.driver.PostgresDriver.api.TableQuery.apply[db.Reports] at source-/scalaproject/src/main/scala/db/package.scala,line-4,offset=88
TableQuery.apply[db.Reports](((tag: Tag) => new db.Reports(tag)))
Apply(TypeApply(Select(Ident(slick.lifted.TableQuery), TermName("apply")), List(TypeTree())), List(Function(List(ValDef(Modifiers(PARAM), TermName("tag"), Ident(slick.lifted.Tag), EmptyTree)), Apply(Select(New(TypeTree()), termNames.CONSTRUCTOR), List(Ident(TermName("tag")))))))
performing macro expansion slick.driver.PostgresDriver.api.TableQuery.apply[db.Records] at source-/scalaproject/src/main/scala/db/package.scala,line-6,offset=154
TableQuery.apply[db.Records](((tag: Tag) => new db.Records(tag)))
Apply(TypeApply(Select(Ident(slick.lifted.TableQuery), TermName("apply")), List(TypeTree())), List(Function(List(ValDef(Modifiers(PARAM), TermName("tag"), Ident(slick.lifted.Tag), EmptyTree)), Apply(Select(New(TypeTree()), termNames.CONSTRUCTOR), List(Ident(TermName("tag")))))))
performing macro expansion `package`.this.materializeClassTag[db.Record]() at source-/scalaproject/src/main/scala/db/Reports.scala,line-69,offset=2078
ClassTag.apply[db.Record](classOf[db.Record])
Apply(TypeApply(Select(Ident(scala.reflect.ClassTag), TermName("apply")), List(TypeTree())), List(Literal(Constant(db.Record))))
performing macro expansion slick.driver.PostgresDriver.api.TableQuery.apply[db.Raws] at source-/scalaproject/src/main/scala/db/package.scala,line-5,offset=121
TableQuery.apply[db.Raws](((tag: Tag) => new db.Raws(tag)))
Apply(TypeApply(Select(Ident(slick.lifted.TableQuery), TermName("apply")), List(TypeTree())), List(Function(List(ValDef(Modifiers(PARAM), TermName("tag"), Ident(slick.lifted.Tag), EmptyTree)), Apply(Select(New(TypeTree()), termNames.CONSTRUCTOR), List(Ident(TermName("tag")))))))
performing macro expansion `package`.this.materializeClassTag[db.Report]() at source-/scalaproject/src/main/scala/db/Reports.scala,line-82,offset=2550
ClassTag.apply[db.Report](classOf[db.Report])
Apply(TypeApply(Select(Ident(scala.reflect.ClassTag), TermName("apply")), List(TypeTree())), List(Literal(Constant(db.Report))))
performing macro expansion `package`.this.materializeClassTag[db.Raw]() at source-/scalaproject/src/main/scala/db/Reports.scala,line-90,offset=2803
ClassTag.apply[db.Raw](classOf[db.Raw])
Apply(TypeApply(Select(Ident(scala.reflect.ClassTag), TermName("apply")), List(TypeTree())), List(Literal(Constant(db.Raw))))
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 1 s, completed Sep 14, 2015 3:08:59 PM

Any ideas how to fix it?

Ákos Vandra-Meyer
  • 1,890
  • 1
  • 23
  • 40
  • Worth taking a look at http://stackoverflow.com/questions/30183000/scala-reflection-to-instantiate-scala-slick-lifted-tablequery/30354736#30354736 to get some ideas – Sean Vieira Sep 14 '15 at 13:25
  • 1
    This post may help [http://stackoverflow.com/questions/32522128/slick-3-reusable-generic-repository/32524071#32524071](http://stackoverflow.com/questions/32522128/slick-3-reusable-generic-repository/32524071#32524071). – Allen Chou Sep 15 '15 at 01:23

0 Answers0