Обновите верхние n строк таблицы в пятно

Я хочу обновить верхние n строк таблицы, а не всю строку при использовании slick 3.0

Это обновление всей версии:

private[this] val active = this.filter(a => a.status =!= AccountStatus.DISABLED)
db.run(
    active.filter(a => a.usedBy.isEmpty || a.usedBy === Host.name)
    .map(account => account.usedBy)
    .update("host-a")
)

Я пытался использовать эту версию, но она не сработала и выкинул исключение

private[this] val active = this.filter(a => a.status =!= AccountStatus.DISABLED)
db.run(
    active.filter(a => a.usedBy.isEmpty || a.usedBy === Host.name)
    .take(10)
    .map(account => account.usedBy)
    .update(Option(Host.name))
)

исключение

Caused by: slick.SlickException: A query for an UPDATE statement must resolve to a comprehension with a single table -- Unsupported shape: Comprehension s2, Some(Apply Function and), None, ConstArray(), None, None, Some(LiteralNode 100 (volatileHint=false)), None
at slick.driver.JdbcStatementBuilderComponent$QueryBuilder.buildUpdate(JdbcStatementBuilderComponent.scala:447)
at slick.driver.JdbcProfile$$anonfun$updateCompiler$1.apply(JdbcProfile.scala:30)
at slick.driver.JdbcProfile$$anonfun$updateCompiler$1.apply(JdbcProfile.scala:30)
at slick.jdbc.JdbcMappingCompilerComponent$JdbcCodeGen.compileServerSideAndMapping(JdbcMappingCompilerComponent.scala:59)

1 ответ

Ну... ответ на этот вопрос заключается в том факте, что вы пытаетесь сделать то, что Слик не должен делать.

Очень простое руководство - если сомневаетесь, думайте о SQL, а затем переходите на Slick

Подумайте, как вы достигнете этого в SQL,

Если я преобразую ваш "запрос",

// lets say Host.name = "Awesome-Host"

active.filter(a => a.usedBy.isEmpty || a.usedBy === Host.name)
  .take(10)
  .map(account => account.usedBy)
  .update(Option(Host.name))

в SQL это будет примерно так,

UPDATE
    active
SET
    used_by = 'Awesome-Host'
WHERE
    used_by IS NULL
    OR used_by = 'Awesome-Host'
LIMIT 10

Что абсурдно с точки зрения SQL...

Теперь... Давайте поговорим о том, как вы на самом деле будете делать это с SQL,

UPDATE
    (
        SELECT 
            *
        FROM
            active
        WHERE
            used_by IS NULL
            OR used_by = 'Awesome-Host'
        LIMIT 10
    ) active_selection
SET
    active_selection.used_by = 'Awesome-Host'

И... это можно перевести на Slick с помощью подзапросов

val activeSelection = active
  .filter(a => a.usedBy.isEmpty || a.usedBy === Host.name)
  .take(10)

val updateSelection = activeSelection
  .map(a => a.usedBy)
  .update(Option(Host.name))
Другие вопросы по тегам