Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions lapis/src/main/kotlin/org/genspectrum/lapis/rhydb/SaneQlAst.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,21 +94,29 @@ data class SaneQlNot(
}

/**
* Variadic `&&` conjunction.
* Variadic `&&` conjunction. Without children, it is `true`.
*/
data class SaneQlAnd(
val children: List<SaneQlExpression>,
) : SaneQlExpression {
override fun render() = children.joinToString(" && ") { wrapIfNeeded(it) }
override fun render() =
when {
children.isEmpty() -> "true"
else -> children.joinToString(" && ") { wrapIfNeeded(it) }
}
}

/**
* Variadic `||` disjunction.
* Variadic `||` disjunction. Without children (e.g. for a filter by an empty list), it is `false`.
*/
data class SaneQlOr(
val children: List<SaneQlExpression>,
) : SaneQlExpression {
override fun render() = children.joinToString(" || ") { wrapIfNeeded(it) }
override fun render() =
when {
children.isEmpty() -> "false"
else -> children.joinToString(" || ") { wrapIfNeeded(it) }
}
}

private fun wrapIfNeeded(expression: SaneQlExpression): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,16 @@ class RhyDbQueryToSaneQlTest {
Or(StringEquals("theColumn", "theValue"), StringEquals("theOtherColumn", "theOtherValue")),
""""theColumn" = 'theValue' || "theOtherColumn" = 'theOtherValue'""",
),
// Empty Or, e.g. from a filter by an empty list
Arguments.of(
Or(emptyList()),
"false",
),
// Empty And
Arguments.of(
And(emptyList()),
"true",
),
// Not
Arguments.of(
Not(StringEquals("theColumn", "theValue")),
Expand Down
16 changes: 16 additions & 0 deletions lapis/src/test/kotlin/org/genspectrum/lapis/rhydb/SaneQlAstTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,22 @@ class SaneQlAstTest {
assertThat(or.render(), equalTo("(true && false) || true"))
}

@Test
fun `GIVEN empty or THEN renders false`() {
assertThat(SaneQlOr(emptyList()).render(), equalTo("false"))
}

@Test
fun `GIVEN empty and THEN renders true`() {
assertThat(SaneQlAnd(emptyList()).render(), equalTo("true"))
}

@Test
fun `GIVEN and with empty or child THEN renders valid SaneQL`() {
val and = SaneQlAnd(listOf(SaneQlOr(emptyList()), SaneQlBoolean(true)))
assertThat(and.render(), equalTo("(false) && true"))
}

@Test
fun `GIVEN and with flat non-and-or children THEN does not add parentheses`() {
val and = SaneQlAnd(listOf(SaneQlBoolean(true), SaneQlBoolean(false)))
Expand Down
Loading