Можно ли определить динамические проекции в Slick?

У меня есть запрос на объединение многих таблиц. Я хотел бы иметь возможность параметризовать, какие поля следует извлекать (иногда сложные функции SQL Postgis). Допустим, исходный запрос построен так:

def buildQuery() = for {
  c <- coffees if c.price > 9.0
  s <- c.supplier
} yield (c.name, s.name)

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

val param = true
def buildQuery() = for {
  c <- coffees if c.price > 9.0
  s <- c.supplier
} yield (c.name, if (param) s.name else null)

Такой код не будет работать, внутренности Slick выдают исключение NullPointerException. Есть ли разумный способ динамически построить часть доходности на основе входных параметров?


person kciesielski    schedule 02.12.2014    source источник


Ответы (1)


Насколько я знаю, вы можете использовать slick case dsl: https://github.com/slick/slick/blob/master/src/main/scala/scala/slick/lifted/Case.scala

person tfh    schedule 02.12.2014
comment
Похоже, что мы не можем добиться нулевого элемента с помощью этого DSL. Кроме того, это работает для Column[], но не для таблиц, как в этом случае: yield (c.name, s) с условием для s. - person kciesielski; 02.12.2014
comment
вы можете реализовать null, используя '... else LiteralNode (null)' - person tfh; 02.12.2014
comment
Вы правы, в 2.1. это ограничено использованием типа Column начиная с ... def Then(res: Column[T])... (см.: github.com/slick/slick/blob/2.1/src/main/scala/scala/s/lifted/). Slick master с другой стороны ограничивает тип до Rep (см.: github.com/slick/slick/blob/master/src/main/scala/scala/slick/), который является базовым типом Column и (!) Table. Должна быть возможность использовать условие на s с изменением, примененным в slick master. - person tfh; 02.12.2014
comment
Я пытался применить это в Slick Activator (с обновленной зависимостью до 2.2.0-SNAPSHOT), но этот код: val cond: Boolean = true; val joinQuery = for { c <- coffees if c.price > 9.0; s <- c.supplier } yield (c.name, Case If cond Then s.name Else LiteralNode("null")) дает довольно много ошибок компиляции. - person kciesielski; 02.12.2014
comment
Попробуйте что-то вроде if (param) s.name.? else null.?, но с помощью Slick's Case DSL. - person cvogt; 09.01.2015