From c3489e17cf662f192adfd97abf5543d0e6360aca Mon Sep 17 00:00:00 2001 From: sviezypan Date: Wed, 26 Jan 2022 22:04:00 +0100 Subject: [PATCH] fix aggregation bug --- core/jvm/src/main/scala/zio/sql/Sql.scala | 9 +- core/jvm/src/main/scala/zio/sql/expr.scala | 17 +- .../jvm/src/main/scala/zio/sql/features.scala | 59 ++-- core/jvm/src/main/scala/zio/sql/select.scala | 306 ++++++++++-------- examples/src/main/scala/Example1.scala | 9 +- .../scala/zio/sql/JdbcInternalModule.scala | 2 +- .../scala/zio/sql/mysql/MysqlModule.scala | 16 +- .../scala/zio/sql/oracle/OracleModule.scala | 16 +- .../zio/sql/postgresql/PostgresModule.scala | 16 +- .../sql/postgresql/PostgresModuleSpec.scala | 8 +- .../zio/sql/sqlserver/SqlServerModule.scala | 16 +- 11 files changed, 264 insertions(+), 210 deletions(-) diff --git a/core/jvm/src/main/scala/zio/sql/Sql.scala b/core/jvm/src/main/scala/zio/sql/Sql.scala index 2b1ce782a..cfef2d88b 100644 --- a/core/jvm/src/main/scala/zio/sql/Sql.scala +++ b/core/jvm/src/main/scala/zio/sql/Sql.scala @@ -17,11 +17,10 @@ trait Sql extends SelectModule with DeleteModule with UpdateModule with ExprModu * * SELECT ARBITRARY(age), COUNT(*) FROM person GROUP BY age */ - def select[F, A, B <: SelectionSet[A]](selection: Selection[F, A, B]): SelectBuilder[F, A, B] = - SelectBuilder(selection) - - def select[F, A, B <: SelectionSet[A]](selection: AggSelection[F, A, B]): AggSelectBuilder[F, A, B] = - AggSelectBuilder(selection) + def select[F, A, B <: SelectionSet[A]](selection: Selection[F, A, B])( + implicit i: Features.IsPartiallyAggregated[F] + ): Selector[F, A, B, i.Unaggregated] = + Selector[F, A, B, i.Unaggregated](selection) def subselect[ParentTable]: SubselectPartiallyApplied[ParentTable] = new SubselectPartiallyApplied[ParentTable] diff --git a/core/jvm/src/main/scala/zio/sql/expr.scala b/core/jvm/src/main/scala/zio/sql/expr.scala index 9918afcba..fa20a7689 100644 --- a/core/jvm/src/main/scala/zio/sql/expr.scala +++ b/core/jvm/src/main/scala/zio/sql/expr.scala @@ -108,14 +108,8 @@ trait ExprModule extends NewtypesModule with FeaturesModule with OpsModule { } } - trait ExprToSelectionLowerPrio { - implicit def expToSelection[F: Features.IsNotAggregated, A, B]( - expr: Expr[F, A, B] - ): Selection[F, A, SelectionSet.Cons[A, B, SelectionSet.Empty]] = - Selection.computedOption(expr, Expr.exprName(expr)) - } + object Expr { - object Expr extends ExprToSelectionLowerPrio { implicit val subqueryToExpr = self.Read.Subselect.subselectToExpr _ sealed trait InvariantExpr[F, -A, B] extends Expr[F, A, B] { @@ -132,14 +126,15 @@ trait ExprModule extends NewtypesModule with FeaturesModule with OpsModule { case _ => None } - implicit def aggregatedExprToSelection[F: Features.IsFullyAggregated, A, B]( + implicit def expToSelection[F, A, B]( expr: Expr[F, A, B] - ): AggSelection[F, A, SelectionSet.Cons[A, B, SelectionSet.Empty]] = - AggSelection.computedOption(expr, exprName(expr)) + ): Selection[F, A, SelectionSet.Cons[A, B, SelectionSet.Empty]] = + Selection.computedOption[F, A, B](expr, Expr.exprName(expr)) + // aggregated F should not be propagated sealed case class Subselect[F <: Features.Aggregated[_], Repr, Source, Subsource, Head]( subselect: Read.Subselect[F, Repr, _ <: Source, Subsource, Head, SelectionSet.Empty] - ) extends InvariantExpr[F, Any, Head] { + ) extends InvariantExpr[Features.Derived, Any, Head] { override def typeTag: TypeTag[Head] = subselect.selection.value.head.toColumn.typeTag } diff --git a/core/jvm/src/main/scala/zio/sql/features.scala b/core/jvm/src/main/scala/zio/sql/features.scala index ca35738e1..34e9e0932 100644 --- a/core/jvm/src/main/scala/zio/sql/features.scala +++ b/core/jvm/src/main/scala/zio/sql/features.scala @@ -2,18 +2,17 @@ package zio.sql import scala.annotation.implicitNotFound -trait FeaturesModule { +trait FeaturesModule { type :||:[A, B] = Features.Union[A, B] - object Features extends PartialAggregationLowerPrio { + object Features { type Aggregated[_] type Union[_, _] type Source[_] - //TODO make Derived and Join tables return Expr of type "Derived" when .columns is called - type Derived type Literal type Function0 + type Derived sealed trait IsNotAggregated[A] object IsNotAggregated { @@ -23,12 +22,12 @@ trait FeaturesModule { implicit def SourceIsNotAggregated[A]: IsNotAggregated[Source[A]] = new IsNotAggregated[Source[A]] {} - implicit val DerivedIsNotAggregated: IsNotAggregated[Derived] = - new IsNotAggregated[Derived] {} - implicit val LiteralIsNotAggregated: IsNotAggregated[Literal] = new IsNotAggregated[Literal] {} + implicit val DerivedIsNotAggregated: IsNotAggregated[Derived] = + new IsNotAggregated[Derived] {} + implicit val Function0IsNotAggregated: IsNotAggregated[Function0] = new IsNotAggregated[Function0] {} } @@ -40,6 +39,8 @@ trait FeaturesModule { implicit def AggregatedIsAggregated[A]: IsFullyAggregated[Aggregated[A]] = new IsFullyAggregated[Aggregated[A]] {} + implicit val LiteralIsAggregated: IsFullyAggregated[Literal] = new IsFullyAggregated[Literal] {} + implicit def UnionIsAggregated[A: IsFullyAggregated, B: IsFullyAggregated]: IsFullyAggregated[Union[A, B]] = new IsFullyAggregated[Union[A, B]] {} } @@ -50,22 +51,44 @@ trait FeaturesModule { object IsSource { implicit def isSource[ColumnIdentity]: IsSource[Source[ColumnIdentity]] = new IsSource[Source[ColumnIdentity]] {} } - } - trait PartialAggregationLowerPrio { - sealed trait IsPartiallyAggregated[A] + sealed trait IsPartiallyAggregated[A] { + type Unaggregated + } - object IsPartiallyAggregated { - - def apply[A](implicit is: IsPartiallyAggregated[A]): IsPartiallyAggregated[A] = is + object IsPartiallyAggregated extends IsPartiallyAggregatedLowPriorityImplicits { + + type WithRemainder[F, R] = IsPartiallyAggregated[F] { + type Unaggregated = R + } + + def apply[A](implicit is: IsPartiallyAggregated[A]): IsPartiallyAggregated.WithRemainder[A, is.Unaggregated] = is - implicit def AggregatedIsAggregated[A]: IsPartiallyAggregated[Features.Aggregated[A]] = new IsPartiallyAggregated[Features.Aggregated[A]] {} + implicit def AggregatedIsAggregated[A]: IsPartiallyAggregated.WithRemainder[Aggregated[A], Any] = new IsPartiallyAggregated[Aggregated[A]] { + override type Unaggregated = Any + } - implicit def UnionIsAggregatedInB[A, B](implicit instB: IsPartiallyAggregated[B]): IsPartiallyAggregated[Features.Union[A, B]] = - new IsPartiallyAggregated[Features.Union[A, B]] {} + implicit def UnionIsAggregated[A, B](implicit inA: IsPartiallyAggregated[A], inB: IsPartiallyAggregated[B]): IsPartiallyAggregated.WithRemainder[Union[A, B], inA.Unaggregated with inB.Unaggregated] = + new IsPartiallyAggregated[Union[A, B]] { + override type Unaggregated = inA.Unaggregated with inB.Unaggregated + } + + implicit val LiteralIsAggregated: IsPartiallyAggregated.WithRemainder[Literal, Any] = new IsPartiallyAggregated[Literal] { + override type Unaggregated = Any + } + + implicit val DerivedIsAggregated: IsPartiallyAggregated.WithRemainder[Derived, Any] = new IsPartiallyAggregated[Derived] { + override type Unaggregated = Any + } + + implicit val FunctionIsAggregated: IsPartiallyAggregated.WithRemainder[Function0, Any] = new IsPartiallyAggregated[Function0] { + override type Unaggregated = Any + } + } - implicit def UnionIsAggregatedInA[A, B](implicit instB: IsPartiallyAggregated[A]): IsPartiallyAggregated[Features.Union[A, B]] = - new IsPartiallyAggregated[Features.Union[A, B]] {} + trait IsPartiallyAggregatedLowPriorityImplicits { + implicit def SourceIsAggregated[A]: IsPartiallyAggregated.WithRemainder[Features.Source[A], Features.Source[A]] = new IsPartiallyAggregated[Features.Source[A]] { override type Unaggregated = Features.Source[A] + } } } } diff --git a/core/jvm/src/main/scala/zio/sql/select.scala b/core/jvm/src/main/scala/zio/sql/select.scala index 9d187cd13..d130ae6aa 100644 --- a/core/jvm/src/main/scala/zio/sql/select.scala +++ b/core/jvm/src/main/scala/zio/sql/select.scala @@ -4,7 +4,52 @@ import scala.language.implicitConversions trait SelectModule { self: ExprModule with TableModule => - sealed case class AggSelectBuilder[F0, Source, B <: SelectionSet[Source]](selection: AggSelection[F0, Source, B]){ +sealed case class Selector[F, Source, B <: SelectionSet[Source], Unaggregated](selection: Selection[F, Source, B]) + +object Selector extends SelectorImplicitLowerPriority { + implicit def aggregatedSelectorToBuilder[F, Source, B <: SelectionSet[Source]] + (selector: Selector[F, Source, B, Any])(implicit i: Features.IsFullyAggregated[F]): SelectBuilder[F, Source, B] = + SelectBuilder(selector.selection) + + implicit def notAggregatedSelectorToBuilder[F, Source, B <: SelectionSet[Source], Unaggregated] + (selector: Selector[F, Source, B, Unaggregated])(implicit i: Features.IsNotAggregated[F]): SelectBuilder[F, Source, B] = + SelectBuilder(selector.selection) +} + +trait SelectorImplicitLowerPriority { + implicit def partiallyAggregatedSelectorToBuilder[F, Source, B <: SelectionSet[Source], Unaggregated] + (selector: Selector[F, Source, B, Unaggregated]): AggSelectBuilder[F, Source, B, Unaggregated] = + AggSelectBuilder[F, Source, B, Unaggregated](selector.selection) + + // select(Sin(1.0)) + implicit def noTable[F, Source >: Any, B <: SelectionSet[Source]]( + selectBuilder: Selector[F, Source, B, Any] + )(implicit + ev: B <:< SelectionSet.Cons[ + Source, + selectBuilder.selection.value.ColumnHead, + selectBuilder.selection.value.SelectionTail + ] + ): Read.Select[ + F, + selectBuilder.selection.value.ResultTypeRepr, + Source, + selectBuilder.selection.value.ColumnHead, + selectBuilder.selection.value.SelectionTail + ] = { + type B0 = SelectionSet.ConsAux[ + selectBuilder.selection.value.ResultTypeRepr, + Source, + selectBuilder.selection.value.ColumnHead, + selectBuilder.selection.value.SelectionTail + ] + val b: B0 = selectBuilder.selection.value.asInstanceOf[B0] + + Read.Subselect(Selection[F, Source, B0](b), None, true) + } +} + + sealed case class AggSelectBuilder[F0, Source, B <: SelectionSet[Source], Unaggregated](selection: Selection[F0, Source, B]){ def from[Source0 <: Source](table: Table.Aux[Source0])(implicit ev: B <:< SelectionSet.Cons[Source0, selection.value.ColumnHead, selection.value.SelectionTail] @@ -13,7 +58,8 @@ trait SelectModule { self: ExprModule with TableModule => selection.value.ResultTypeRepr, Source0, selection.value.ColumnHead, - selection.value.SelectionTail + selection.value.SelectionTail, + Unaggregated ] = { type B0 = SelectionSet.ConsAux[ selection.value.ResultTypeRepr, @@ -23,62 +69,125 @@ trait SelectModule { self: ExprModule with TableModule => ] val b: B0 = selection.value.asInstanceOf[B0] - AggSelectBuilderGroupBy(Read.Subselect(Selection[F0, Source0, B0](b), Some(table), true, Nil)) + AggSelectBuilderGroupBy[F0, selection.value.ResultTypeRepr, Source0, selection.value.ColumnHead, selection.value.SelectionTail, Unaggregated](Read.Subselect(Selection[F0, Source0, B0](b), Some(table), true)) } } - sealed trait AggVerifier[MainF, F1] - object AggVerifier { - - implicit def unionOf[MainF, F1, Remainder]( - implicit - ev1: MainF <:< Features.Union[F1, Remainder], - ev2: Features.IsFullyAggregated[Remainder] - ) : AggVerifier[MainF, F1] = new AggVerifier[MainF, F1] {} - - implicit def unionOfB[MainF, F1, Remainder]( - implicit - ev1: MainF <:< Features.Union[Remainder, F1], - ev2: Features.IsFullyAggregated[Remainder] - ) : AggVerifier[MainF, F1] = new AggVerifier[MainF, F1] {} - } - - // Features.Union[Features.Union[Features.Source[String("customer_id")], Features.Source[String("order_date")],] - // Features.Aggregated[Features.Source[String("id")]]] - - // select customer_id, order_date, count(id) - // from orders - // group by customer_id - - - // Features.Source[String("customer_id")] - //Features.Source[String("order_date")] - - // we require all the Exprs which are not aggregated from partially aggregated F and any other - // F here is always aggregated - sealed case class AggSelectBuilderGroupBy[F, Repr, Source, Head, Tail <: SelectionSet[Source]]( + //TODO add having + sealed case class AggSelectBuilderGroupBy[F, Repr, Source, Head, Tail <: SelectionSet[Source], Unaggregated]( select: Read.Select[F, Repr, Source, Head, Tail]) { import Read.ExprSet._ // format: off def groupBy[F1, B](expr: Expr[F1, Source, B])( - implicit - ev1: Features.IsNotAggregated[F1], - ev2: AggVerifier[F, F1] + implicit ev1: F1 =:= Unaggregated ): Read.Select[F, Repr, Source, Head, Tail] = - select.copy(groupByExprs2 = NoExpr ++ expr) + select.copy(groupByExprs = NoExpr ++ expr) - def groupBy[F1, F2](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any]): Read.Select[F, Repr, Source, Head, Tail] = - select.copy(groupByExprs2 = NoExpr ++ expr ++ expr2) - - def groupBy[F1, F2, F3](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any]): Read.Select[F, Repr, Source, Head, Tail] = - select.copy(groupByExprs2 = NoExpr ++ expr ++ expr2 ++ expr3) - - def groupBy[F1, F2, F3, F4](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any]): Read.Select[F, Repr, Source, Head, Tail] = - select.copy(groupByExprs2 = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4) - - def groupBy[F1, F2, F3, F4, F5](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any]): Read.Select[F, Repr, Source, Head, Tail] = - select.copy(groupByExprs2 = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5) + def groupBy[F1, F2](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any])( + implicit ev1: F1 with F2 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2) + + def groupBy[F1, F2, F3](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any])( + implicit ev1: F1 with F2 with F3 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3) + + def groupBy[F1, F2, F3, F4](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4) + + def groupBy[F1, F2, F3, F4, F5](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5) + + def groupBy[F1, F2, F3, F4, F5, F6](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6) + + def groupBy[F1, F2, F3, F4, F5, F6, F7](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F10, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F10, Source, Any], expr11: Expr[F11, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any], expr14: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 with F14 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13 ++ expr14) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any], expr14: Expr[F9, Source, Any], expr15: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 with F14 with F15 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13 ++ expr14 ++ expr15) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any], expr14: Expr[F9, Source, Any], expr15: Expr[F9, Source, Any], expr16: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 with F14 with F15 with F16 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13 ++ expr14 ++ expr15 ++ expr16) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any], expr14: Expr[F9, Source, Any], expr15: Expr[F9, Source, Any], expr16: Expr[F9, Source, Any], expr17: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 with F14 with F15 with F16 with F17 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13 ++ expr14 ++ expr15 ++ expr16 ++ expr17) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any], expr14: Expr[F9, Source, Any], expr15: Expr[F9, Source, Any], expr16: Expr[F9, Source, Any], expr17: Expr[F9, Source, Any], expr18: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 with F14 with F15 with F16 with F17 with F18 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13 ++ expr14 ++ expr15 ++ expr16 ++ expr17 ++ expr18) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any], expr14: Expr[F9, Source, Any], expr15: Expr[F9, Source, Any], expr16: Expr[F9, Source, Any], expr17: Expr[F9, Source, Any], expr18: Expr[F9, Source, Any], expr19: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 with F14 with F15 with F16 with F17 with F18 with F19 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13 ++ expr14 ++ expr15 ++ expr16 ++ expr17 ++ expr18 ++ expr19) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any], expr14: Expr[F9, Source, Any], expr15: Expr[F9, Source, Any], expr16: Expr[F9, Source, Any], expr17: Expr[F9, Source, Any], expr18: Expr[F9, Source, Any], expr19: Expr[F9, Source, Any], expr20: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 with F14 with F15 with F16 with F17 with F18 with F19 with F20 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13 ++ expr14 ++ expr15 ++ expr16 ++ expr17 ++ expr18 ++ expr19 ++ expr20) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any], expr14: Expr[F9, Source, Any], expr15: Expr[F9, Source, Any], expr16: Expr[F9, Source, Any], expr17: Expr[F9, Source, Any], expr18: Expr[F9, Source, Any], expr19: Expr[F9, Source, Any], expr20: Expr[F9, Source, Any], expr21: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 with F14 with F15 with F16 with F17 with F18 with F19 with F20 with F21<:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13 ++ expr14 ++ expr15 ++ expr16 ++ expr17 ++ expr18 ++ expr19 ++ expr20 ++ expr21) + + def groupBy[F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22](expr: Expr[F1, Source, Any], expr2: Expr[F2, Source, Any], expr3: Expr[F3, Source, Any], expr4: Expr[F4, Source, Any], expr5: Expr[F5, Source, Any], expr6: Expr[F6, Source, Any], expr7: Expr[F7, Source, Any], expr8: Expr[F8, Source, Any], expr9: Expr[F9, Source, Any], expr10: Expr[F9, Source, Any], expr11: Expr[F9, Source, Any], expr12: Expr[F9, Source, Any], expr13: Expr[F9, Source, Any], expr14: Expr[F9, Source, Any], expr15: Expr[F9, Source, Any], expr16: Expr[F9, Source, Any], expr17: Expr[F9, Source, Any], expr18: Expr[F9, Source, Any], expr19: Expr[F9, Source, Any], expr20: Expr[F9, Source, Any], expr21: Expr[F9, Source, Any], expr22: Expr[F9, Source, Any])( + implicit ev1: F1 with F2 with F3 with F4 with F5 with F6 with F7 with F8 with F9 with F10 with F11 with F12 with F13 with F14 with F15 with F16 with F17 with F18 with F19 with F20 with F21 with F22 <:< Unaggregated + ): Read.Select[F, Repr, Source, Head, Tail] = + select.copy(groupByExprs = NoExpr ++ expr ++ expr2 ++ expr3 ++ expr4 ++ expr5 ++ expr6 ++ expr7 ++ expr8 ++ expr9 ++ expr10 ++ expr11 ++ expr12 ++ expr13 ++ expr14 ++ expr15 ++ expr16 ++ expr17 ++ expr18 ++ expr19 ++ expr20 ++ expr21 ++ expr22) // format: on } @@ -101,45 +210,13 @@ trait SelectModule { self: ExprModule with TableModule => ] val b: B0 = selection.value.asInstanceOf[B0] - Read.Subselect(Selection[F0, Source0, B0](b), Some(table), true, Nil) - } - } - - object SelectBuilder { - implicit def noTable[F, Source >: Any, B <: SelectionSet[Source]]( - selectBuilder: SelectBuilder[F, Source, B] - )(implicit - ev: B <:< SelectionSet.Cons[ - Source, - selectBuilder.selection.value.ColumnHead, - selectBuilder.selection.value.SelectionTail - ] - ): Read.Select[ - F, - selectBuilder.selection.value.ResultTypeRepr, - Source, - selectBuilder.selection.value.ColumnHead, - selectBuilder.selection.value.SelectionTail - ] = { - type B0 = SelectionSet.ConsAux[ - selectBuilder.selection.value.ResultTypeRepr, - Source, - selectBuilder.selection.value.ColumnHead, - selectBuilder.selection.value.SelectionTail - ] - val b: B0 = selectBuilder.selection.value.asInstanceOf[B0] - - Read.Subselect(Selection[F, Source, B0](b), None, true) + Read.Subselect(Selection[F0, Source0, B0](b), Some(table), true) } } final class SubselectPartiallyApplied[ParentTable] { def apply[F, A, B <: SelectionSet[A]](selection: Selection[F, A, B]): SubselectBuilder[F, A, B, ParentTable] = SubselectBuilder(selection) - - //TODO fix - def apply[F, A, B <: SelectionSet[A]](selection: AggSelection[F, A, B]): SubselectBuilder[F, A, B, ParentTable] = - ??? //SubselectBuilder(selection) } sealed case class SubselectBuilder[F, Source, B <: SelectionSet[Source], ParentTable]( @@ -424,12 +501,11 @@ trait SelectModule { self: ExprModule with TableModule => selection: Selection[F, Source, SelectionSet.ConsAux[Repr, Source, Head, Tail]], table: Option[Table.Aux[Subsource]], whereExpr: Expr[_, Source, Boolean], - groupByExprs: List[Expr[_, Source, Any]] = Nil, + groupByExprs: ExprSet[Source] = ExprSet.NoExpr, havingExpr: Expr[_, Source, Boolean] = true, orderByExprs: List[Ordering[Expr[_, Source, Any]]] = Nil, offset: Option[Long] = None, //todo don't know how to do this outside of postgres/mysql - limit: Option[Long] = None, - groupByExprs2: ExprSet[Source] = ExprSet.NoExpr + limit: Option[Long] = None ) extends Read[Repr] { self => def where(whereExpr2: Expr[_, Source, Boolean]): Subselect[F, Repr, Source, Subsource, Head, Tail] = @@ -445,25 +521,18 @@ trait SelectModule { self: ExprModule with TableModule => ): Subselect[F, Repr, Source, Subsource, Head, Tail] = copy(orderByExprs = self.orderByExprs ++ (o :: os.toList)) - def having(havingExpr2: Expr[_, Source, Boolean]) - // (implicit - // ev: Features.IsAggregated[F] - // ) - : Subselect[F, Repr, Source, Subsource, Head, Tail] = { - //val _ = ev + def having(havingExpr2: Expr[_, Source, Boolean])(implicit + ev: Features.IsFullyAggregated[F] + ): Subselect[F, Repr, Source, Subsource, Head, Tail] = { + val _ = ev copy(havingExpr = self.havingExpr && havingExpr2) } - /** - * what about this? xD - * select count(customer_id), count(id), '1' as "Hi" - from orders - group by "Hi" - */ - //TODO we can allow group by but only by Source.Expr, (at this point F is FullyAggregated) - // TODO found a way how to make Features.IsSource implicit for all Fs in varargs - def groupBy[X: Features.IsNotAggregated](key: Expr[X, Source, Any], keys: Expr[_, Source, Any]*): Subselect[F, Repr, Source, Subsource, Head, Tail] = { - copy(groupByExprs = groupByExprs ++ (key :: keys.toList)) + def groupBy(key: Expr[_, Source, Any], keys: Expr[_, Source, Any]*)(implicit + ev: Features.IsFullyAggregated[F] + ): Subselect[F, Repr, Source, Subsource, Head, Tail] = { + val _ = ev + copy(groupByExprs = (key :: keys.toList).foldLeft[ExprSet[Source]](ExprSet.NoExpr)((tail, head) => ExprSet.ExprCons(head, tail))) } override def asTable( @@ -488,7 +557,7 @@ trait SelectModule { self: ExprModule with TableModule => object Subselect { implicit def subselectToExpr[F <: Features.Aggregated[_], Repr, Source, Subsource, Head]( subselect: Read.Subselect[F, Repr, _ <: Source, Subsource, Head, SelectionSet.Empty] - ): Expr[F, Any, Head] = + ): Expr[Features.Derived, Any, Head] = Expr.Subselect(subselect) } @@ -533,29 +602,6 @@ trait SelectModule { self: ExprModule with TableModule => def lit[B: TypeTag](values: B*): Read[(B, Unit)] = Literal(values.toSeq) } - sealed case class AggSelection[F, -A, +B <: SelectionSet[A]](value: B) { self => - - type ColsRepr = value.ResultTypeRepr - - def ++[F2, A1 <: A, C <: SelectionSet[A1]]( - that: Selection[F2, A1, C] - ): AggSelection[F :||: F2, A1, self.value.Append[A1, C]] = - AggSelection(self.value ++ that.value) - - //TODO this is not correct by => age ++ Count(id) ++ Count(id) - def ++[F2, A1 <: A, C <: SelectionSet[A1]]( - that: AggSelection[F2, A1, C] - )(implicit ev: Features.IsFullyAggregated[F]): Selection[F :||: F2, A1, self.value.Append[A1, C]] = - Selection(self.value ++ that.value) - } - - object AggSelection { - import ColumnSelection._ - import SelectionSet.{ Cons, Empty } - def computedOption[F, A, B](expr: Expr[F, A, B], name: Option[ColumnName]): AggSelection[F, A, Cons[A, B, Empty]] = - AggSelection(Cons(Computed(expr, name), Empty)) - } - /** * A columnar selection of `B` from a source `A`, modeled as `A => B`. */ @@ -566,17 +612,7 @@ trait SelectModule { self: ExprModule with TableModule => def ++[F2, A1 <: A, C <: SelectionSet[A1]]( that: Selection[F2, A1, C] ): Selection[F :||: F2, A1, self.value.Append[A1, C]] = - Selection(self.value ++ that.value) - - def ++[F2, A1 <: A, C <: SelectionSet[A1]]( - that: AggSelection[F2, A1, C] - ): AggSelection[F :||: F2, A1, self.value.Append[A1, C]] = - AggSelection(self.value ++ that.value) - - // (Arbitrary(age)) ++ (Count(1)) => Selection - // age ++ (Count(1)) => AggSelection - // (Count(1)) ++ age => AggSelection - // age ++ name => Selection + Selection[F :||: F2, A1, self.value.Append[A1, C]](self.value ++ that.value) } object Selection { diff --git a/examples/src/main/scala/Example1.scala b/examples/src/main/scala/Example1.scala index a2283f889..01610c6c9 100644 --- a/examples/src/main/scala/Example1.scala +++ b/examples/src/main/scala/Example1.scala @@ -38,8 +38,6 @@ object Example1 extends Sql { select((age as "age") ++ (age2 as "age2")) .from(table.join(table2).on(name === name2)) - val xx = (Arbitrary(age) as "age") ++ (Count(1) as "count") - val aggregated = select((Arbitrary(age) as "age") ++ (Count(1) as "count")) .from(table) @@ -59,5 +57,10 @@ object Example1 extends Sql { val query = select(fkCustomerId ++ Count(orderId)) .from(orders) - .groupBy(fkCustomerId) + .groupBy(fkCustomerId, orderDate) + + //TODO remove - just to test group by / having + def test[F, A, B](expr: Expr[F,A, B])(implicit in: Features.IsPartiallyAggregated[F]) : in.Unaggregated = ??? + def test2[F, A, B <: SelectionSet[A]](selection: Selection[F, A, B])(implicit in: Features.IsPartiallyAggregated[F]) : in.Unaggregated = ??? + } diff --git a/jdbc/src/main/scala/zio/sql/JdbcInternalModule.scala b/jdbc/src/main/scala/zio/sql/JdbcInternalModule.scala index 38715d2c5..d8da0c9ca 100644 --- a/jdbc/src/main/scala/zio/sql/JdbcInternalModule.scala +++ b/jdbc/src/main/scala/zio/sql/JdbcInternalModule.scala @@ -109,7 +109,7 @@ trait JdbcInternalModule { self: Jdbc => read match { case Read.Mapped(read, _) => getColumns(read) - case Read.Subselect(selection, _, _, _, _, _, _, _, _) => + case Read.Subselect(selection, _, _, _, _, _, _, _) => selection.value.selectionsUntyped.toVector.map(_.asInstanceOf[ColumnSelection[_, _]]).map { case t @ ColumnSelection.Constant(_, _) => t.typeTag case t @ ColumnSelection.Computed(_, _) => t.typeTag diff --git a/mysql/src/main/scala/zio/sql/mysql/MysqlModule.scala b/mysql/src/main/scala/zio/sql/mysql/MysqlModule.scala index 59ac2f0fd..f5bcc2223 100644 --- a/mysql/src/main/scala/zio/sql/mysql/MysqlModule.scala +++ b/mysql/src/main/scala/zio/sql/mysql/MysqlModule.scala @@ -85,7 +85,7 @@ trait MysqlModule extends Jdbc { self => case Read.Mapped(read, _) => renderReadImpl(read) - case read0 @ Read.Subselect(_, _, _, _, _, _, _, _, _) => + case read0 @ Read.Subselect(_, _, _, _, _, _, _, _) => object Dummy { type F type Repr @@ -109,7 +109,7 @@ trait MysqlModule extends Jdbc { self => renderExpr(whereExpr) } groupByExprs match { - case _ :: _ => + case Read.ExprSet.ExprCons(_, _) => render(" GROUP BY ") renderExprList(groupByExprs) @@ -119,7 +119,7 @@ trait MysqlModule extends Jdbc { self => render(" HAVING ") renderExpr(havingExpr) } - case Nil => () + case Read.ExprSet.NoExpr => () } orderByExprs match { case _ :: _ => @@ -401,17 +401,17 @@ trait MysqlModule extends Jdbc { self => } } - private def renderExprList(expr: List[Expr[_, _, _]])(implicit render: Renderer): Unit = + private def renderExprList(expr: Read.ExprSet[_])(implicit render: Renderer): Unit = expr match { - case head :: tail => + case Read.ExprSet.ExprCons(head, tail) => renderExpr(head) tail match { - case _ :: _ => + case Read.ExprSet.ExprCons(_, _) => render(", ") renderExprList(tail) - case Nil => () + case Read.ExprSet.NoExpr => () } - case Nil => () + case Read.ExprSet.NoExpr => () } def renderOrderingList(expr: List[Ordering[Expr[_, _, _]]])(implicit render: Renderer): Unit = diff --git a/oracle/src/main/scala/zio/sql/oracle/OracleModule.scala b/oracle/src/main/scala/zio/sql/oracle/OracleModule.scala index 8aabe9c42..86e368493 100644 --- a/oracle/src/main/scala/zio/sql/oracle/OracleModule.scala +++ b/oracle/src/main/scala/zio/sql/oracle/OracleModule.scala @@ -133,7 +133,7 @@ trait OracleModule extends Jdbc { self => read match { case Read.Mapped(read, _) => buildReadString(read, builder) - case read0 @ Read.Subselect(_, _, _, _, _, _, _, _, _) => + case read0 @ Read.Subselect(_, _, _, _, _, _, _, _) => object Dummy { type F type Repr @@ -157,7 +157,7 @@ trait OracleModule extends Jdbc { self => buildExpr(whereExpr, builder) } groupByExprs match { - case _ :: _ => + case Read.ExprSet.ExprCons(_, _) => builder.append(" GROUP BY ") buildExprList(groupByExprs, builder) @@ -167,7 +167,7 @@ trait OracleModule extends Jdbc { self => builder.append(" HAVING ") buildExpr(havingExpr, builder) } - case Nil => () + case Read.ExprSet.NoExpr => () } orderByExprs match { case _ :: _ => @@ -199,17 +199,17 @@ trait OracleModule extends Jdbc { self => val _ = builder.append(" (").append(values.mkString(",")).append(") ") //todo fix needs escaping } - def buildExprList(expr: List[Expr[_, _, _]], builder: StringBuilder): Unit = + def buildExprList(expr: Read.ExprSet[_], builder: StringBuilder): Unit = expr match { - case head :: tail => + case Read.ExprSet.ExprCons(head, tail) => buildExpr(head, builder) tail match { - case _ :: _ => + case Read.ExprSet.ExprCons(_, _) => builder.append(", ") buildExprList(tail, builder) - case Nil => () + case Read.ExprSet.NoExpr => () } - case Nil => () + case Read.ExprSet.NoExpr => () } def buildOrderingList(expr: List[Ordering[Expr[_, _, _]]], builder: StringBuilder): Unit = expr match { diff --git a/postgres/src/main/scala/zio/sql/postgresql/PostgresModule.scala b/postgres/src/main/scala/zio/sql/postgresql/PostgresModule.scala index eb1506268..d7f75a544 100644 --- a/postgres/src/main/scala/zio/sql/postgresql/PostgresModule.scala +++ b/postgres/src/main/scala/zio/sql/postgresql/PostgresModule.scala @@ -670,7 +670,7 @@ trait PostgresModule extends Jdbc { self => private[zio] def renderReadImpl(read: self.Read[_])(implicit render: Renderer): Unit = read match { case Read.Mapped(read, _) => renderReadImpl(read) - case read0 @ Read.Subselect(_, _, _, _, _, _, _, _, _) => + case read0 @ Read.Subselect(_, _, _, _, _, _, _, _) => object Dummy { type F type Repr @@ -695,7 +695,7 @@ trait PostgresModule extends Jdbc { self => renderExpr(whereExpr) } groupByExprs match { - case _ :: _ => + case Read.ExprSet.ExprCons(_, _) => render(" GROUP BY ") renderExprList(groupByExprs) @@ -705,7 +705,7 @@ trait PostgresModule extends Jdbc { self => render(" HAVING ") renderExpr(havingExpr) } - case Nil => () + case Read.ExprSet.NoExpr => () } orderByExprs match { case _ :: _ => @@ -732,17 +732,17 @@ trait PostgresModule extends Jdbc { self => render(" (", values.mkString(","), ") ") //todo fix needs escaping } - def renderExprList(expr: List[Expr[_, _, _]])(implicit render: Renderer): Unit = + def renderExprList(expr: Read.ExprSet[_])(implicit render: Renderer): Unit = expr match { - case head :: tail => + case Read.ExprSet.ExprCons(head, tail) => renderExpr(head) tail match { - case _ :: _ => + case Read.ExprSet.ExprCons(_, _) => render(", ") renderExprList(tail) - case Nil => () + case Read.ExprSet.NoExpr => () } - case Nil => () + case Read.ExprSet.NoExpr => () } def renderOrderingList(expr: List[Ordering[Expr[_, _, _]]])(implicit render: Renderer): Unit = diff --git a/postgres/src/test/scala/zio/sql/postgresql/PostgresModuleSpec.scala b/postgres/src/test/scala/zio/sql/postgresql/PostgresModuleSpec.scala index 7e2996bea..c06ff3510 100644 --- a/postgres/src/test/scala/zio/sql/postgresql/PostgresModuleSpec.scala +++ b/postgres/src/test/scala/zio/sql/postgresql/PostgresModuleSpec.scala @@ -388,19 +388,17 @@ object PostgresModuleSpec extends PostgresRunnableSpec with ShopSchema { */ import AggregationDef._ - import Ordering._ val expected = List(6,5,5,5,4) val query = select(fkCustomerId ++ Count(orderId)) .from(orders) - //.groupBy(fkCustomerId) + .groupBy(fkCustomerId) + .orderBy(Ordering.Desc(Count(orderId))) - val actual = execute(query.to[Long, Int](_.toInt)).runCollect.map(_.toList) + val actual = execute(query.to[UUID, Long, Int]((_: UUID, count: Long) => count.toInt)).runCollect.map(_.toList) assertM(actual)(equalTo(expected)) - - ??? }, testM("insert - 1 rows into customers") { diff --git a/sqlserver/src/main/scala/zio/sql/sqlserver/SqlServerModule.scala b/sqlserver/src/main/scala/zio/sql/sqlserver/SqlServerModule.scala index 77cdbfaee..6907eb20b 100644 --- a/sqlserver/src/main/scala/zio/sql/sqlserver/SqlServerModule.scala +++ b/sqlserver/src/main/scala/zio/sql/sqlserver/SqlServerModule.scala @@ -251,7 +251,7 @@ trait SqlServerModule extends Jdbc { self => case Read.Mapped(read, _) => buildReadString(read.asInstanceOf[Read[Out]]) //todo offset (needs orderBy, must use fetch _instead_ of top) - case read0 @ Read.Subselect(_, _, _, _, _, _, _, _, _) => + case read0 @ Read.Subselect(_, _, _, _, _, _, _, _) => object Dummy { type F type Repr @@ -280,7 +280,7 @@ trait SqlServerModule extends Jdbc { self => buildExpr(whereExpr) } groupByExprs match { - case _ :: _ => + case Read.ExprSet.ExprCons(_, _) => builder.append(" group by ") buildExprList(groupByExprs) @@ -290,7 +290,7 @@ trait SqlServerModule extends Jdbc { self => builder.append(" having ") buildExpr(havingExpr) } - case Nil => () + case Read.ExprSet.NoExpr => () } orderByExprs match { case _ :: _ => @@ -309,17 +309,17 @@ trait SqlServerModule extends Jdbc { self => val _ = builder.append(" (").append(values.mkString(",")).append(") ") //todo fix needs escaping } - def buildExprList(expr: List[Expr[_, _, _]]): Unit = + def buildExprList(expr: Read.ExprSet[_]): Unit = expr match { - case head :: tail => + case Read.ExprSet.ExprCons(head, tail) => buildExpr(head) tail match { - case _ :: _ => + case Read.ExprSet.ExprCons(_, _) => builder.append(", ") buildExprList(tail) - case Nil => () + case Read.ExprSet.NoExpr => () } - case Nil => () + case Read.ExprSet.NoExpr => () } def buildOrderingList(expr: List[Ordering[Expr[_, _, _]]]): Unit = expr match {