Файлы playframework evolutions, совместимые как с postgres, так и с h2 - PullRequest
3 голосов
/ 20 сентября 2011

Я разрабатывал веб-сайт с платформой Play (scala), используя H2 в качестве бэкэнда. Тестирование хорошо интегрировано, особенно с возможностью запускать тесты в отношении H2 db в памяти.

Теперь я бы хотел перенести свое хранилище данных в Postgres по разным причинам. Это оставляет меня с проблемой: как продолжить тестирование и сохранить простоту свежего БД для каждого запуска теста? Я вижу в сети, что некоторым людям удается запустить вживую против postgres и протестировать против H2. Однако они не полностью совместимы на уровне SQL (даже с H2 в режиме совместимости с Postgres). Например, SERIAL, BIGSERIAL и BYTEA не поддерживаются в H2.

Могу ли я сделать это, используя ограниченное совместимое пересечение обоих диалектов, или мне не хватает другой техники?

Спасибо за любую помощь.

Alex

Ответы [ 2 ]

1 голос
/ 01 апреля 2016

я знаю, что это старая статья, но похоже, что еще несколько лет спустя не было очевидного решения.в качестве кратковременного исправления, в игре 2.4.x-2.5.x (пока только тестируемой там), вы можете изменить способ применения эволюций во время тестов, создав специальный считыватель эволюций:

package support

import play.api.db.evolutions.{ClassLoaderEvolutionsReader, Evolutions, ResourceEvolutionsReader}

import java.io.{ByteArrayInputStream, InputStream}
import java.nio.charset.StandardCharsets
import scala.io.Source
import scala.util.Try

class EvolutionTransformingReader(
    classLoader: ClassLoader = classOf[ClassLoaderEvolutionsReader].getClassLoader,
    prefix: String = "")
  extends ResourceEvolutionsReader {

  def loadResource(db: String, revision: Int): Option[InputStream] =
    for {
      stream <- Option(classLoader.getResourceAsStream(prefix + Evolutions.resourceName(db, revision)))
      lines <- Try(Source.fromInputStream(stream).getLines).toOption
      updated = lines map convertPostgresLinesToH2
    } yield convertLinesToInputStream(updated)

  private val ColumnRename = """(?i)\s*ALTER TABLE (\w+) RENAME COLUMN (\w+) TO (\w+);""".r

  private def convertPostgresLinesToH2(line: String): String =
    line match {
      case ColumnRename(tableName, oldColumn, newColumn) =>
        s"""ALTER TABLE $tableName ALTER COLUMN $oldColumn RENAME TO $newColumn;"""
      case _ => line
    }

  private def convertLinesToInputStream(lines: Iterator[String]): InputStream =
    new ByteArrayInputStream(lines.mkString("\n").getBytes(StandardCharsets.UTF_8))
}

затемпередайте его в то место, где вы применяете эволюции во время ваших тестов:

Evolutions.applyEvolutions(registry.database, new EvolutionTransformingReader())

обратите внимание, что читатель все еще находится в довольно тупом состоянии (предполагается, что операторы SQL являются однострочниками, что не гарантируется), но этодолжно быть достаточно, чтобы кто-нибудь начал.

1 голос
/ 22 сентября 2011

Поскольку файлы эволюции напрямую используют SQL, если вы не ограничены общим кросс-db-совместимым подмножеством SQL, у вас могут возникнуть проблемы.

Реального решения по этому поводу не существует, но вы все равно можете использовать свежую базу данных для тестирования. Просто установите следующее:

%test.jpa.ddl=create-drop
%test.db.driver=org.postgresql.Driver
%test.db=<jdbc url>
//etc

Это должно создать новое соединение postgres для тестирования, создать базу данных с нуля, запустить эволюцию, выполнить тесты и удалить все данные после завершения.

...