Extend query builder with more functions

This commit is contained in:
Eike Kettner 2020-12-15 23:08:15 +01:00
parent 4ca6dfccae
commit f3855628d5
5 changed files with 69 additions and 12 deletions

View File

@ -13,9 +13,9 @@ object DBFunction {
case class Count(column: Column[_]) extends DBFunction
case class Max(column: Column[_]) extends DBFunction
case class Max(expr: SelectExpr) extends DBFunction
case class Min(column: Column[_]) extends DBFunction
case class Min(expr: SelectExpr) extends DBFunction
case class Coalesce(expr: SelectExpr, exprs: Vector[SelectExpr]) extends DBFunction
@ -25,6 +25,12 @@ object DBFunction {
case class Substring(expr: SelectExpr, start: Int, length: Int) extends DBFunction
case class Cast(expr: SelectExpr, newType: String) extends DBFunction
case class Avg(expr: SelectExpr) extends DBFunction
case class Sum(expr: SelectExpr) extends DBFunction
sealed trait Operator
object Operator {
case object Plus extends Operator

View File

@ -68,11 +68,26 @@ trait DSL extends DoobieMeta {
def countAll: DBFunction =
DBFunction.CountAll
def max(e: SelectExpr): DBFunction =
DBFunction.Max(e)
def max(c: Column[_]): DBFunction =
DBFunction.Max(c)
max(c.s)
def min(expr: SelectExpr): DBFunction =
DBFunction.Min(expr)
def min(c: Column[_]): DBFunction =
DBFunction.Min(c)
min(c.s)
def avg(expr: SelectExpr): DBFunction =
DBFunction.Avg(expr)
def sum(expr: SelectExpr): DBFunction =
DBFunction.Sum(expr)
def cast(expr: SelectExpr, targetType: String): DBFunction =
DBFunction.Cast(expr, targetType)
def coalesce(expr: SelectExpr, more: SelectExpr*): DBFunction.Coalesce =
DBFunction.Coalesce(expr, more.toVector)

View File

@ -29,8 +29,8 @@ sealed trait Select {
def groupBy(gb: GroupBy): Select
def groupBy(c: Column[_]): Select =
groupBy(GroupBy(c))
def groupBy(c: Column[_], cs: Column[_]*): Select =
groupBy(GroupBy(c, cs: _*))
def limit(batch: Batch): Select =
this match {
@ -63,6 +63,8 @@ sealed trait Select {
where(c.getOrElse(Condition.unit))
def where(c: Condition): Select
def unwrap: Select.SimpleSelect
}
object Select {
@ -98,12 +100,18 @@ object Select {
where: Condition,
groupBy: Option[GroupBy]
) extends Select {
def unwrap: Select.SimpleSelect =
this
def groupBy(gb: GroupBy): SimpleSelect =
copy(groupBy = Some(gb))
def distinct: SimpleSelect =
copy(distinctFlag = true)
def noDistinct: SimpleSelect =
copy(distinctFlag = false)
def where(c: Condition): SimpleSelect =
copy(where = c)
@ -119,11 +127,14 @@ object Select {
def changeWhere(f: Condition => Condition): SimpleSelect =
copy(where = f(where))
def orderBy(ob: OrderBy, obs: OrderBy*): Select =
def orderBy(ob: OrderBy, obs: OrderBy*): Ordered =
Ordered(this, ob, obs.toVector)
}
case class RawSelect(fragment: Fragment) extends Select {
def unwrap: Select.SimpleSelect =
sys.error("Cannot unwrap RawSelect")
def groupBy(gb: GroupBy): Select =
sys.error("RawSelect doesn't support adding group by clause")
@ -147,6 +158,9 @@ object Select {
}
case class Union(q: Select, qs: Vector[Select]) extends Select {
def unwrap: Select.SimpleSelect =
q.unwrap
def groupBy(gb: GroupBy): Union =
copy(q = q.groupBy(gb))
@ -170,6 +184,9 @@ object Select {
}
case class Intersect(q: Select, qs: Vector[Select]) extends Select {
def unwrap: Select.SimpleSelect =
q.unwrap
def groupBy(gb: GroupBy): Intersect =
copy(q = q.groupBy(gb))
@ -194,6 +211,9 @@ object Select {
case class Ordered(q: Select, orderBy: OrderBy, orderBys: Vector[OrderBy])
extends Select {
def unwrap: Select.SimpleSelect =
q.unwrap
def groupBy(gb: GroupBy): Ordered =
copy(q = q.groupBy(gb))
@ -215,6 +235,9 @@ object Select {
}
case class Limit(q: Select, batch: Batch) extends Select {
def unwrap: Select.SimpleSelect =
q.unwrap
def groupBy(gb: GroupBy): Limit =
copy(q = q.groupBy(gb))
@ -236,6 +259,9 @@ object Select {
}
case class WithCte(cte: CteBind, ctes: Vector[CteBind], q: Select) extends Select {
def unwrap: Select.SimpleSelect =
q.unwrap
def groupBy(gb: GroupBy): WithCte =
copy(q = q.groupBy(gb))

View File

@ -16,11 +16,11 @@ object DBFunctionBuilder extends CommonBuilder {
case DBFunction.Count(col) =>
sql"COUNT(" ++ column(col) ++ fr")"
case DBFunction.Max(col) =>
sql"MAX(" ++ column(col) ++ fr")"
case DBFunction.Max(expr) =>
sql"MAX(" ++ SelectExprBuilder.build(expr) ++ fr")"
case DBFunction.Min(col) =>
sql"MIN(" ++ column(col) ++ fr")"
case DBFunction.Min(expr) =>
sql"MIN(" ++ SelectExprBuilder.build(expr) ++ fr")"
case DBFunction.Coalesce(expr, exprs) =>
val v = exprs.prepended(expr).map(SelectExprBuilder.build)
@ -37,6 +37,16 @@ object DBFunctionBuilder extends CommonBuilder {
buildOperator(op) ++
SelectExprBuilder.build(right)
case DBFunction.Cast(f, newType) =>
sql"CAST(" ++ SelectExprBuilder.build(f) ++
fr" AS" ++ Fragment.const(newType) ++
sql")"
case DBFunction.Avg(expr) =>
sql"AVG(" ++ SelectExprBuilder.build(expr) ++ fr")"
case DBFunction.Sum(expr) =>
sql"SUM(" ++ SelectExprBuilder.build(expr) ++ fr")"
}
def buildOperator(op: DBFunction.Operator): Fragment =

View File

@ -86,7 +86,7 @@ object QCollective {
select(t.all).append(count(ti.itemId).s),
from(ti).innerJoin(t, ti.tagId === t.tid),
t.cid === coll
).group(GroupBy(t.name, t.tid, t.category))
).groupBy(t.name, t.tid, t.category)
sql.build.query[TagCount].to[List]
}