При создании табличного запроса я хотел бы изменить свой оператор выбора, сопоставив табличный запрос по умолчанию. Однако я не могу найти способ сопоставить значение столбца и по-прежнему сопоставлять с моим классом case
case class MyRecord(id: Int, name: String, value: Int)
class MyTable(tag: Tag) extends Table[MyRecord](tag, "MYTABLE") {
def id = column[Int]("id")
def name = column[String]("name")
def value = column[Int]("value")
def * = (id, name, value) <> (MyRecord.tupled, MyRecord.unapply)
}
lazy val tableQuery = TableQuery[MyTable]
Я хотел бы обрезать значение name
с помощью этой функции:
def trimLeading0: (Rep[String]) => Rep[String] = SimpleExpression.unary[String, String] {
(str, queryBuilder) =>
import slick.util.MacroSupport._
import queryBuilder._
b"TRIM(LEADING 0 FROM $str)"
}
Теперь я в недоумении, что делать здесь:
val trimmedTableQuery: Query[MyTable, MyRecord, Seq] = tableQuery.map(s => ???)
Я попытался сопоставить Rep
, как я сделал бы с классом case:
val trimmedTableQuery = tableQuery.map(s => s.copy(name = trimLeading0(s.name)))
Это отказывается компилироваться с value copy is not a member of MyTable
Мой текущий обходной путь — использовать пользовательскую функцию вместо MyRecord.tupled
для проекции по умолчанию:
def trimming(t: (Int, String, Int)) = MyRecord(t._1, t._2.dropWhile(_ == "0"), t._3)
def * = (id, name, value) <> (trimming, MyRecord.unapply)
В качестве альтернативы я мог бы сопоставить возвращаемый результат DBIOAction
, возвращающего кортеж, с классом case, что гораздо менее элегантно:
val action = tableQuery.map{ s => (s.id, trimLeading0(s.name), s.value)}.result
val futureTuples: Future[Seq[(Int, String, Int)]] = db.run(action)
val records = futureTuples map (s => s.map(MyRecord.tupled))
Но как я могу сделать это внутри метода map
при построении запроса? ИЛИ было бы лучше изменить описание столбца def name
?