Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用Slick 3验证模式_Scala_Slick_Typesafe_Slick 3.0 - Fatal编程技术网

Scala 使用Slick 3验证模式

Scala 使用Slick 3验证模式,scala,slick,typesafe,slick-3.0,Scala,Slick,Typesafe,Slick 3.0,我希望在Scala应用程序中使用Slick 3框架来管理数据库交互。我已经能够使用Slick自动生成必要的表对象,但我还希望进行一个集成测试,以验证数据库中的模式是否与对象中的模式匹配。这是因为有时表会在没有通知我的团队的情况下被更改,因此我们更希望在集成测试中而不是在生产应用程序中捕获更改 一种方法是简单地在测试运行程序中的每个表上运行select查询。然而,我觉得应该有一个更直接的方法。此外,我不清楚如何系统地运行文件中定义的所有表,除了手动将table对象附加到测试运行程序运行的某个序列之

我希望在Scala应用程序中使用Slick 3框架来管理数据库交互。我已经能够使用Slick自动生成必要的表对象,但我还希望进行一个集成测试,以验证数据库中的模式是否与对象中的模式匹配。这是因为有时表会在没有通知我的团队的情况下被更改,因此我们更希望在集成测试中而不是在生产应用程序中捕获更改

一种方法是简单地在测试运行程序中的每个表上运行select查询。然而,我觉得应该有一个更直接的方法。此外,我不清楚如何系统地运行文件中定义的所有表,除了手动将table对象附加到测试运行程序运行的某个序列之外。我注意到有一个schema字段,但它只能生成create和drop语句

任何帮助都将不胜感激。谢谢大家!

编辑:

这是我的解决方案,但我希望有一个更好的:

class TablesIT extends FunSuite with BeforeAndAfter with ScalaFutures {
  var db: Database = _
  before{ db = Database.forURL( /* personal details */ )}

  object ResultMap extends GetResult[Map[String,Any]] { //Object borrowed from http://stackoverflow.com/questions/20262036/slick-query-multiple-tables-databases-with-getting-column-names
    def apply(pr: PositionedResult) = {
      val rs = pr.rs // <- jdbc result set
      val md = rs.getMetaData
      val res = (1 to pr.numColumns).map{ i=> md.getColumnName(i) -> rs.getObject(i) }.toMap
      pr.nextRow // <- use Slick's advance method to avoid endless loop
      res
    }
  }

  def testTableHasCols[A <: Table[_]](table: slick.lifted.TableQuery[A]): Unit = {
    whenReady(db.run(table.take(1).result.headOption.asTry)) { case Success(t) => t match {
      case Some(r) => logTrace(r.toString)
      case None => logTrace("Empty table")
    }
    case Failure(ex) => fail("Query exception: " + ex.toString)
    }
  }

  def plainSqlSelect[A](query: String)(implicit gr: GetResult[A]): Future[Seq[A]] = {
    val stmt = sql"""#$query""".as[A]
    db.run(stmt)
  }


  def compareNumOfCols[A <: Table[_]](table: slick.lifted.TableQuery[A]) = {
    val tableName = table.baseTableRow.tableName
    val selectStar = whenReady(db.run(sql"""select * from #$tableName limit 1""".as(ResultMap).headOption)) {
      case Some(m) => m.size
      case None => 0
    }
    val model = whenReady(db.run(sql"""#${table.take(1).result.statements.head}""".as(ResultMap).headOption)) {
      case Some(m) => m.size
      case None => 0
    }
    assert(selectStar === model, "The number of columns do not match")
  }

  test("Test table1") {
    testTableHasCols(Table1)
    compareNumOfCols(Table1)
  }

// And on for each table
}

我最终想出了一个更好的解决方案,使用了以下想法。它或多或少是相同的,不幸的是,我仍然必须为每个表手动创建一个测试,但我认为该方法更简洁。但是,请注意,由于信息模式的原因,这只适用于PostgreSQL,但其他数据库系统有其他方法

class TablesIT extends FunSuite with BeforeAndAfter with ScalaFutures {
  var db: Database = _
  before{ db = Database.forURL( /* personal details */ )}

  def testTableHasCols[A <: Table[_]](table: slick.lifted.TableQuery[A]): Unit = {
    whenReady(db.run(table.take(1).result.headOption.asTry)) { case Success(t) => t match {
      case Some(r) => logTrace(r.toString)
      case None => logTrace("Empty table")
    }
    case Failure(ex) => fail("Query exception: " + ex.toString)
    }
  }

  def compareNumOfCols[A <: Table[_]](table: slick.lifted.TableQuery[A]) = {
    val tableName = table.baseTableRow.tableName
    val selectStar = whenReady(db.run(sql"""select column_name from information_schema.columns where table_name='#$tableName'""".as[String])) {
      case m: Seq[String] => m.size
      case _ => 0
    }
    val model = table.baseTableRow.create_*.map(_.name).toSeq.size

    assert(selectStar === model, "The number of columns do not match")
  }

  test("Test table1") {
    testTableHasCols(Table1)
    compareNumOfCols(Table1)
  }

// And on for each table
}

你还有别的想法吗?是的,事实上。请注意,根据设计,这并不强制表中列的顺序。