Slick + Dynamic TableQuery

时间:2015-09-14 13:06:44

标签: scala slick scala-macros scala-2.11 slick-3.0

对于我自己(主要是教学 - 理解光滑背后的黑魔法和scala的反射API)的目的,我想创建一个能够创建表的函数,如果数据库中缺少该表,这样的API:

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)

我的尝试是这样的:

  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
      }
    }
  }

其中,我想应该运行,但会产生以下输出(scala 2.11.7):

  

编译

[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
  

开启宏调试:

[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

任何想法如何解决?

0 个答案:

没有答案