Kotlin Exposed - выбор на основе количества подзапросов - PullRequest
0 голосов
/ 23 сентября 2019

В моей модели данных у меня очень простое отношение один-ко-многим между вызовами и элементами белого списка .

Я пытаюсь выбрать вызовфильтруется по белому списку.В основном, критерии выбора задачи заключаются в том, что в случае, если в запросе нет ни одной записи в белом списке для себя, или белый список не совпадает по имени.

Это может быть достигнуто с помощью довольно простого запроса SQL:

select c.* from challenge c, challenge_whitelist w where (c.id = w."challengeId" and w."userName" = 'testuser') or ((select count(*) where c.id = w."challengeId") = 0);

Я не могу перевести его на Exposed, хотя:

  // will not compile
  fun listAll(userName: String) {
    ExposedChallenge.wrapRows(
      ChallengeTable.innerJoin(ChallengeWhitelistTable)
        .slice(ChallengeTable.columns)
        .select((ChallengeWhitelistTable.userName eq userName) or (ChallengeTable.innerJoin(ChallengeWhitelistTable).selectAll().count() eq 0))
    ).toList()
  }

Проверка userName работает правильно, но ChallengeTable.innerJoin(ChallengeWhitelistTable).selectAll().count() eq 0) не квалифицируется как допустимое выражение (не компилируется).

Обратите внимание, что сопоставления очень просты:

object ChallengeTable : IntIdTable() {
  val createdAt = datetime("createdAt")
}

class ExposedChallenge(id: EntityID<Int>) : IntEntity(id) {
  companion object : IntEntityClass<ExposedChallenge>(ChallengeTable)
  var createdAt by ChallengeTable.createdAt
  val whitelist by ExposedChallengeWhitelist referrersOn ChallengeWhitelistTable.challenge
}

object ChallengeWhitelistTable : IntIdTable(name = "challenge_whitelist") {
  var userName = varchar("userName", 50)
  var challengeId = integer("challengeId")
  val challenge = reference("challengeId", ChallengeTable).uniqueIndex()
}

class ExposedChallengeWhitelist(id: EntityID<Int>) : IntEntity(id) {
  companion object : IntEntityClass<ExposedChallengeWhitelist>(ChallengeWhitelistTable)

  val challengeId by ChallengeWhitelistTable.challengeId
  val challenge by ExposedChallenge referencedOn ChallengeWhitelistTable.challenge
}

Буду признателен за любую помощь.

1 Ответ

0 голосов
/ 24 сентября 2019

Ваш SQL-запрос недопустим, так как вы используете select count(*) без from части.Но его можно переписать с помощью Exposed DSL, например:

ChallengeTable.leftJoin(ChallengeWhitelistTable).
    slice(ChallengeTable.columns).
    selectAll().
    groupBy(ChallengeTable.id, ChallengeWhitelistTable.userName).having {
    (ChallengeWhitelistTable.userName eq "testUser") or
    (ChallengeWhitelistTable.id.count() eq 0)
}

Другой способ - использовать только левое соединение:

ChallengeTable.innerJoin(ChallengeWhitelistTable).
    slice(ChallengeTable.columns).
    select {
        (ChallengeWhitelistTable.userName eq "testUser") or
        (ChallengeWhitelistTable.id.isNull())
    }
...