mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 10:28:27 +00:00
Add anonymous subselects to query builder
This commit is contained in:
@ -7,6 +7,7 @@
|
|||||||
package docspell.store.qb
|
package docspell.store.qb
|
||||||
|
|
||||||
import cats.data.{NonEmptyList => Nel}
|
import cats.data.{NonEmptyList => Nel}
|
||||||
|
import cats.syntax.option._
|
||||||
|
|
||||||
import docspell.store.qb.impl.SelectBuilder
|
import docspell.store.qb.impl.SelectBuilder
|
||||||
|
|
||||||
@ -23,6 +24,9 @@ sealed trait Select {
|
|||||||
def as(alias: String): SelectExpr.SelectQuery =
|
def as(alias: String): SelectExpr.SelectQuery =
|
||||||
SelectExpr.SelectQuery(this, Some(alias))
|
SelectExpr.SelectQuery(this, Some(alias))
|
||||||
|
|
||||||
|
def asSubSelect: SelectExpr.SelectQuery =
|
||||||
|
SelectExpr.SelectQuery(this, None)
|
||||||
|
|
||||||
/** Adds one or more order-by definitions */
|
/** Adds one or more order-by definitions */
|
||||||
def orderBy(ob: OrderBy, obs: OrderBy*): Select
|
def orderBy(ob: OrderBy, obs: OrderBy*): Select
|
||||||
|
|
||||||
@ -71,35 +75,38 @@ sealed trait Select {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Select {
|
object Select {
|
||||||
|
def apply(projection: SelectExpr) =
|
||||||
|
SimpleSelect(false, Nel.of(projection), None, Condition.unit, None)
|
||||||
|
|
||||||
def apply(projection: Nel[SelectExpr], from: FromExpr) =
|
def apply(projection: Nel[SelectExpr], from: FromExpr) =
|
||||||
SimpleSelect(false, projection, from, Condition.unit, None)
|
SimpleSelect(false, projection, from.some, Condition.unit, None)
|
||||||
|
|
||||||
def apply(projection: SelectExpr, from: FromExpr) =
|
def apply(projection: SelectExpr, from: FromExpr) =
|
||||||
SimpleSelect(false, Nel.of(projection), from, Condition.unit, None)
|
SimpleSelect(false, Nel.of(projection), from.some, Condition.unit, None)
|
||||||
|
|
||||||
def apply(
|
def apply(
|
||||||
projection: Nel[SelectExpr],
|
projection: Nel[SelectExpr],
|
||||||
from: FromExpr,
|
from: FromExpr,
|
||||||
where: Condition
|
where: Condition
|
||||||
) = SimpleSelect(false, projection, from, where, None)
|
) = SimpleSelect(false, projection, from.some, where, None)
|
||||||
|
|
||||||
def apply(
|
def apply(
|
||||||
projection: SelectExpr,
|
projection: SelectExpr,
|
||||||
from: FromExpr,
|
from: FromExpr,
|
||||||
where: Condition
|
where: Condition
|
||||||
) = SimpleSelect(false, Nel.of(projection), from, where, None)
|
) = SimpleSelect(false, Nel.of(projection), from.some, where, None)
|
||||||
|
|
||||||
def apply(
|
def apply(
|
||||||
projection: Nel[SelectExpr],
|
projection: Nel[SelectExpr],
|
||||||
from: FromExpr,
|
from: FromExpr,
|
||||||
where: Condition,
|
where: Condition,
|
||||||
groupBy: GroupBy
|
groupBy: GroupBy
|
||||||
) = SimpleSelect(false, projection, from, where, Some(groupBy))
|
) = SimpleSelect(false, projection, from.some, where, Some(groupBy))
|
||||||
|
|
||||||
case class SimpleSelect(
|
case class SimpleSelect(
|
||||||
distinctFlag: Boolean,
|
distinctFlag: Boolean,
|
||||||
projection: Nel[SelectExpr],
|
projection: Nel[SelectExpr],
|
||||||
from: FromExpr,
|
from: Option[FromExpr],
|
||||||
where: Condition,
|
where: Condition,
|
||||||
groupBy: Option[GroupBy]
|
groupBy: Option[GroupBy]
|
||||||
) extends Select {
|
) extends Select {
|
||||||
@ -125,7 +132,7 @@ object Select {
|
|||||||
copy(projection = es)
|
copy(projection = es)
|
||||||
|
|
||||||
def changeFrom(f: FromExpr => FromExpr): SimpleSelect =
|
def changeFrom(f: FromExpr => FromExpr): SimpleSelect =
|
||||||
copy(from = f(from))
|
copy(from = from.map(f))
|
||||||
|
|
||||||
def changeWhere(f: Condition => Condition): SimpleSelect =
|
def changeWhere(f: Condition => Condition): SimpleSelect =
|
||||||
copy(where = f(where))
|
copy(where = f(where))
|
||||||
|
@ -33,6 +33,8 @@ object SelectExpr {
|
|||||||
case class SelectLiteral(value: String, alias: Option[String]) extends SelectExpr {
|
case class SelectLiteral(value: String, alias: Option[String]) extends SelectExpr {
|
||||||
def as(a: String): SelectLiteral =
|
def as(a: String): SelectLiteral =
|
||||||
copy(alias = Some(a))
|
copy(alias = Some(a))
|
||||||
|
def as(otherCol: Column[_]): SelectExpr =
|
||||||
|
copy(alias = Some(otherCol.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
case class SelectQuery(query: Select, alias: Option[String]) extends SelectExpr {
|
case class SelectQuery(query: Select, alias: Option[String]) extends SelectExpr {
|
||||||
|
@ -52,7 +52,7 @@ object SelectBuilder {
|
|||||||
|
|
||||||
def buildSimple(sq: Select.SimpleSelect): Fragment = {
|
def buildSimple(sq: Select.SimpleSelect): Fragment = {
|
||||||
val f0 = sq.projection.map(selectExpr).reduceLeft(_ ++ comma ++ _)
|
val f0 = sq.projection.map(selectExpr).reduceLeft(_ ++ comma ++ _)
|
||||||
val f1 = fromExpr(sq.from)
|
val f1 = sq.from.map(fromExpr).getOrElse(Fragment.empty)
|
||||||
val f2 = cond(sq.where)
|
val f2 = cond(sq.where)
|
||||||
val f3 = sq.groupBy.map(groupBy).getOrElse(Fragment.empty)
|
val f3 = sq.groupBy.map(groupBy).getOrElse(Fragment.empty)
|
||||||
f0 ++ f1 ++ f2 ++ f3
|
f0 ++ f1 ++ f2 ++ f3
|
||||||
|
@ -50,9 +50,11 @@ class QueryBuilderTest extends FunSuite with TestLoggingConfig {
|
|||||||
)
|
)
|
||||||
assertEquals(11, proj.size)
|
assertEquals(11, proj.size)
|
||||||
from match {
|
from match {
|
||||||
case FromExpr.From(_) =>
|
case None =>
|
||||||
fail("Unexpected from value")
|
fail("Unexpected from value")
|
||||||
case FromExpr.Joined(f, joins) =>
|
case Some(FromExpr.From(_)) =>
|
||||||
|
fail("Unexpected from value")
|
||||||
|
case Some(FromExpr.Joined(f, joins)) =>
|
||||||
assertEquals(f, FromExpr.From(c))
|
assertEquals(f, FromExpr.From(c))
|
||||||
assertEquals(2, joins.size)
|
assertEquals(2, joins.size)
|
||||||
joins.head match {
|
joins.head match {
|
||||||
|
Reference in New Issue
Block a user