Использование функции БД (TRIM (LEADING '0' from column)) в Slick

Я хотел бы перевести SQL-запрос в TableQuery:

SELECT ..., TRIM(LEADING '0' FROM mycolumn) FROM mytable WHERE TRIM(LEADING '0' FROM mycolumn) = '$key

Должно стать MyTableQuery.filter(<_.mycolumn something something> )

Я не могу использовать implicit MappedColumnType, потому что я сопоставляю String с String и в результате есть другие столбцы String. И я понятия не имею, как я буду использовать его как в SELECT, так и в WHERE.

Для части SELECT я создал пользовательскую функцию для сопоставления кортежей результатов с моим классом case, поэтому мне нужно решение только для части WHERE.

Прочитаны Исходя из SQL и Определяемые пользователем функции из документации, но, к сожалению, я ничего не понимаю. Я полагаю, что мог бы использовать SimpleFunction.unary[String, String], но не понял, как это сделать.

Обычный String я бы обрезал dropLeft, однако у Rep[String] такого метода нет. ltrim не принимает параметр. endsWith неоднозначно в моем случае.

Я не могу дополнить свой запрос String, так как не все значения в БД дополняются и имеют разную длину.

Я определенно могу использовать простой SQL и отображать результаты, но мне бы очень хотелось понять, чего мне здесь не хватает.

Я использую Slick 3.1.1.


person kostja    schedule 02.02.2016    source источник


Ответы (1)


Немного странный синтаксис TRIM(LEADING означает, что вы должны отказаться от использования SimpleExpression и использовать QueryBuilder, который дает вам доступ к.

val trimLeading = SimpleExpression.binary[String, String, String] {
  (trimChar, str, queryBuilder) =>
    import slick.util.MacroSupport._
    import queryBuilder._
    b"TRIM(LEADING $trimChar FROM $str)"
}

и вот пример, который это реализует

import com.typesafe.config.ConfigFactory
import slick.backend.DatabaseConfig
import slick.driver.JdbcProfile
import scala.concurrent.duration.Duration
import scala.concurrent.Await

object TrimLeading extends App {
  def trimLeadingExample(dbConfig: DatabaseConfig[JdbcProfile]): Unit = {
    import dbConfig.driver.api._
    val trimLeading = SimpleExpression.binary[String, String, String] {
      (trimChar, str, queryBuilder) =>
        import slick.util.MacroSupport._
        import queryBuilder._
        b"TRIM(LEADING $trimChar FROM $str)"
    }

    class ZeroTable(tag: Tag) extends Table[String](tag, "ZeroTable") {
      def zeros = column[String]("zeros")
      def * = zeros
    }
    val zeroTable = TableQuery[ZeroTable]
    exec(zeroTable.schema.create)
    exec(zeroTable ++= Seq("000000x", "00x", "000000000x", "00000x", "00xx"))

    exec(zeroTable.
          filter(s => trimLeading("0", s.zeros) === "x").
          map(s => trimLeading("0", s.zeros)).result).foreach(println)
    exec(zeroTable.schema.drop)
    def exec[T](action: DBIO[T]): T = Await.result(dbConfig.db.run(action), Duration.Inf)
  }
  val configStr =
    """
      |  driver = "freeslick.OracleProfile$"
      |  db {
      |    driver = oracle.jdbc.OracleDriver
      |    url="jdbc:oracle:thin:@//localhost:49161/xe"
      |    properties = {
      |      databaseName = "freeslicktest"
      |      user = "system"
      |      password = "oracle"
      |    }
      |  }
    """.stripMargin
  trimLeadingExample(DatabaseConfig.forConfig[JdbcProfile]("", ConfigFactory.parseString(configStr)))
}

и из журналов, заявление

*** (s.jdbc.JdbcBackend.statement) Preparing statement: select TRIM(LEADING '0' FROM "zeros") from "ZeroTable" where TRIM(LEADING '0' FROM "zeros") = 'x'

person Sue C    schedule 06.02.2016
comment
Вау, спасибо, Сью С, все отлично работает! По крайней мере, в предложении where, где мне это действительно нужно. Использование SimpleExpression в предложении select (map) работает нормально только до тех пор, пока у меня все в порядке с возвратом кортежей. Возможно, вы могли бы взглянуть на дополнительный вопрос? Не большая проблема, просто любопытство. - person kostja; 07.02.2016