问题
I would like to translate an SQL query into a TableQuery
:
SELECT ..., TRIM(LEADING '0' FROM mycolumn) FROM mytable WHERE TRIM(LEADING '0' FROM mycolumn) = '$key
Should become MyTableQuery.filter(<_.mycolumn something something> )
I cannot use an implicit MappedColumnType
because I am mapping from String
to String
and have other String
columns in the result. And I have no idea how I would use it in both SELECT
and WHERE
For the SELECT
part, I have created a custom function for mapping the result tuples to my case class, so I only need a solution for the WHERE
part.
Have read the Coming from SQL and User defined features from the docs but unfortunately, I am none the wiser. I suppose I could use a SimpleFunction.unary[String, String]
but have not figured out how.
I would trim a regular String
with dropLeft
, however Rep[String]
does not have such a method. ltrim
does not accept a parameter. endsWith
is ambiguous in my case.
I cannot pad my query String
, since not all values in the DB are padded and have different lengths.
I definitely can use plain SQL and map the results, but I would really like to understand what I am missing here.
I am using Slick 3.1.1
回答1:
The slightly odd syntax of TRIM(LEADING means you have to drop to using a SimpleExpression and use the QueryBuilder that gives you access to.
val trimLeading = SimpleExpression.binary[String, String, String] {
(trimChar, str, queryBuilder) =>
import slick.util.MacroSupport._
import queryBuilder._
b"TRIM(LEADING $trimChar FROM $str)"
}
and here is an example that exercises it
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)))
}
and from the logs, the statement is
*** (s.jdbc.JdbcBackend.statement) Preparing statement: select TRIM(LEADING '0' FROM "zeros") from "ZeroTable" where TRIM(LEADING '0' FROM "zeros") = 'x'
来源:https://stackoverflow.com/questions/35155869/using-db-function-trimleading-0-from-column-in-slick