diff --git a/modules/store/src/main/scala/docspell/store/qb/DBFunction.scala b/modules/store/src/main/scala/docspell/store/qb/DBFunction.scala index 86ad7b1a..dc418810 100644 --- a/modules/store/src/main/scala/docspell/store/qb/DBFunction.scala +++ b/modules/store/src/main/scala/docspell/store/qb/DBFunction.scala @@ -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 diff --git a/modules/store/src/main/scala/docspell/store/qb/DSL.scala b/modules/store/src/main/scala/docspell/store/qb/DSL.scala index fe3bda42..ce28d56e 100644 --- a/modules/store/src/main/scala/docspell/store/qb/DSL.scala +++ b/modules/store/src/main/scala/docspell/store/qb/DSL.scala @@ -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) diff --git a/modules/store/src/main/scala/docspell/store/qb/Select.scala b/modules/store/src/main/scala/docspell/store/qb/Select.scala index d6c17113..d6150b18 100644 --- a/modules/store/src/main/scala/docspell/store/qb/Select.scala +++ b/modules/store/src/main/scala/docspell/store/qb/Select.scala @@ -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)) diff --git a/modules/store/src/main/scala/docspell/store/qb/impl/DBFunctionBuilder.scala b/modules/store/src/main/scala/docspell/store/qb/impl/DBFunctionBuilder.scala index d99302e8..16c3e33f 100644 --- a/modules/store/src/main/scala/docspell/store/qb/impl/DBFunctionBuilder.scala +++ b/modules/store/src/main/scala/docspell/store/qb/impl/DBFunctionBuilder.scala @@ -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 = diff --git a/modules/store/src/main/scala/docspell/store/queries/QCollective.scala b/modules/store/src/main/scala/docspell/store/queries/QCollective.scala index 696d2294..b9fe40c7 100644 --- a/modules/store/src/main/scala/docspell/store/queries/QCollective.scala +++ b/modules/store/src/main/scala/docspell/store/queries/QCollective.scala @@ -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] }