From ffb088aa158898b77dabe90ce67a5efceb5f0aea Mon Sep 17 00:00:00 2001 From: NPCRUS Date: Thu, 27 Mar 2025 12:03:27 +0100 Subject: [PATCH 1/3] initial commit --- docs/reference.md | 124 ++++++++++++++++++++++ scalasql/query/src/Select.scala | 24 +++++ scalasql/query/src/SimpleSelect.scala | 8 ++ scalasql/test/src/query/SelectTests.scala | 70 ++++++++++++ 4 files changed, 226 insertions(+) diff --git a/docs/reference.md b/docs/reference.md index 23058509..2a3db58c 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -738,6 +738,130 @@ ShippingInfo.select +### Select.filterIf.filter not added + + + +```scala +ShippingInfo.select.filterIf(false)(_.buyerId `=` 2) +``` + + +* + ```sql + SELECT + shipping_info0.id AS id, + shipping_info0.buyer_id AS buyer_id, + shipping_info0.shipping_date AS shipping_date + FROM shipping_info shipping_info0 + ``` + + + +* + ```scala + Seq( + ShippingInfo[Sc](1, 2, LocalDate.parse("2010-02-03")), + ShippingInfo[Sc](2, 1, LocalDate.parse("2012-04-05")), + ShippingInfo[Sc](3, 2, LocalDate.parse("2012-05-06")) + ) + ``` + + + +### Select.filterIf.filter added + + + +```scala +ShippingInfo.select.filterIf(true)(_.buyerId `=` 2) +``` + + +* + ```sql + SELECT + shipping_info0.id AS id, + shipping_info0.buyer_id AS buyer_id, + shipping_info0.shipping_date AS shipping_date + FROM shipping_info shipping_info0 + WHERE (shipping_info0.buyer_id = ?) + ``` + + + +* + ```scala + Seq( + ShippingInfo[Sc](1, 2, LocalDate.parse("2010-02-03")), + ShippingInfo[Sc](3, 2, LocalDate.parse("2012-05-06")) + ) + ``` + + + +### Select.filterOpt.filter not added + + + +```scala +ShippingInfo.select.filterOpt[Int](None)((value, table) => table.buyerId `=` value) +``` + + +* + ```sql + SELECT + shipping_info0.id AS id, + shipping_info0.buyer_id AS buyer_id, + shipping_info0.shipping_date AS shipping_date + FROM shipping_info shipping_info0 + ``` + + + +* + ```scala + Seq( + ShippingInfo[Sc](1, 2, LocalDate.parse("2010-02-03")), + ShippingInfo[Sc](2, 1, LocalDate.parse("2012-04-05")), + ShippingInfo[Sc](3, 2, LocalDate.parse("2012-05-06")) + ) + ``` + + + +### Select.filterOpt.filter added + + + +```scala +ShippingInfo.select.filterOpt(Some(2))((value, table) => table.buyerId `=` value) +``` + + +* + ```sql + SELECT + shipping_info0.id AS id, + shipping_info0.buyer_id AS buyer_id, + shipping_info0.shipping_date AS shipping_date + FROM shipping_info shipping_info0 + WHERE (shipping_info0.buyer_id = ?) + ``` + + + +* + ```scala + Seq( + ShippingInfo[Sc](1, 2, LocalDate.parse("2010-02-03")), + ShippingInfo[Sc](3, 2, LocalDate.parse("2012-05-06")) + ) + ``` + + + ### Select.map.single `.map` allows you to select exactly what you want to return from diff --git a/scalasql/query/src/Select.scala b/scalasql/query/src/Select.scala index a493cba0..8b15701b 100644 --- a/scalasql/query/src/Select.scala +++ b/scalasql/query/src/Select.scala @@ -101,6 +101,21 @@ trait Select[Q, R] */ def withFilter(f: Q => Expr[Boolean]): Select[Q, R] = filter(f) + /** + * Filters this [[Select]] with the given predicate, if [[cond]] evaluates to true + */ + def filterIf(cond: Boolean)( + f: Q => Expr[Boolean] + ): Select[Q, R] + + /** + * Filters this [[Select]] with the given predicate consuming provided option as a part of predicate's input, + * if this option is Some[T] + */ + def filterOpt[T](option: Option[T])( + f: (T, Q) => Expr[Boolean] + ): Select[Q, R] + /** * Performs one or more aggregates in a single [[Select]] */ @@ -214,6 +229,9 @@ trait Select[Q, R] */ def head: Query.Single[R] = take(1).single + // TODO + // def headOption: Query.Single[Option[R]] = take(1).single + /** * Converts this [[Select]] into an [[Expr]], assuming it returns a single row and * a single column. Note that if this returns multiple rows, behavior is database-specific, @@ -325,6 +343,12 @@ object Select { override def filter(f: Q => Expr[Boolean]): Select[Q, R] = selectToSimpleSelect().filter(f) + override def filterIf(cond: Boolean)(f: Q => Expr[Boolean]): Select[Q, R] = + selectToSimpleSelect().filterIf(cond)(f) + + override def filterOpt[T](option: Option[T])(f: (T, Q) => Expr[Boolean]): Select[Q, R] = + selectToSimpleSelect().filterOpt(option)(f) + override def aggregate[E, V](f: Aggregatable.Proxy[Q] => E)( implicit qr: Queryable.Row[E, V] ): Aggregate[E, V] = selectToSimpleSelect().aggregate(f) diff --git a/scalasql/query/src/SimpleSelect.scala b/scalasql/query/src/SimpleSelect.scala index 04e97a39..b177f79d 100644 --- a/scalasql/query/src/SimpleSelect.scala +++ b/scalasql/query/src/SimpleSelect.scala @@ -95,6 +95,14 @@ class SimpleSelect[Q, R]( else copy(groupBy0 = groupBy0.map(g => g.copy(having = g.having ++ Seq(f(expr))))) } + def filterIf(cond: Boolean)(f: Q => Expr[Boolean]): Select[Q, R] = + if (cond) this.filter(f) else this + + def filterOpt[T](option: Option[T])(f: (T, Q) => Expr[Boolean]): Select[Q, R] = option match { + case None => this + case Some(opt) => this.filter(q => f(opt, q)) + } + def join0[Q2, R2, QF, RF]( prefix: String, other: Joinable[Q2, R2], diff --git a/scalasql/test/src/query/SelectTests.scala b/scalasql/test/src/query/SelectTests.scala index 969c3e42..f74fd971 100644 --- a/scalasql/test/src/query/SelectTests.scala +++ b/scalasql/test/src/query/SelectTests.scala @@ -141,6 +141,76 @@ trait SelectTests extends ScalaSqlSuite { ) } + test("filterIf") { + test("filter not added") - checker( + query = Text { ShippingInfo.select.filterIf(false)(_.buyerId `=` 2) }, + sql = """ + SELECT + shipping_info0.id AS id, + shipping_info0.buyer_id AS buyer_id, + shipping_info0.shipping_date AS shipping_date + FROM shipping_info shipping_info0 + """, + value = Seq( + ShippingInfo[Sc](1, 2, LocalDate.parse("2010-02-03")), + ShippingInfo[Sc](2, 1, LocalDate.parse("2012-04-05")), + ShippingInfo[Sc](3, 2, LocalDate.parse("2012-05-06")) + ), + docs = "" + ) + test("filter added") - checker( + query = Text { ShippingInfo.select.filterIf(true)(_.buyerId `=` 2) }, + sql = """ + SELECT + shipping_info0.id AS id, + shipping_info0.buyer_id AS buyer_id, + shipping_info0.shipping_date AS shipping_date + FROM shipping_info shipping_info0 + WHERE (shipping_info0.buyer_id = ?) + """, + value = Seq( + ShippingInfo[Sc](1, 2, LocalDate.parse("2010-02-03")), + ShippingInfo[Sc](3, 2, LocalDate.parse("2012-05-06")) + ), + docs = "" + ) + } + + test("filterOpt") { + test("filter not added") - checker( + query = Text { ShippingInfo.select.filterOpt[Int](None)((value, table) => table.buyerId `=` value) }, + sql = """ + SELECT + shipping_info0.id AS id, + shipping_info0.buyer_id AS buyer_id, + shipping_info0.shipping_date AS shipping_date + FROM shipping_info shipping_info0 + """, + value = Seq( + ShippingInfo[Sc](1, 2, LocalDate.parse("2010-02-03")), + ShippingInfo[Sc](2, 1, LocalDate.parse("2012-04-05")), + ShippingInfo[Sc](3, 2, LocalDate.parse("2012-05-06")) + ), + docs = "" + ) + test("filter added") - checker( + query = Text { ShippingInfo.select.filterOpt(Some(2))((value, table) => table.buyerId `=` value) }, + sql = """ + SELECT + shipping_info0.id AS id, + shipping_info0.buyer_id AS buyer_id, + shipping_info0.shipping_date AS shipping_date + FROM shipping_info shipping_info0 + WHERE (shipping_info0.buyer_id = ?) + """, + value = Seq( + ShippingInfo[Sc](1, 2, LocalDate.parse("2010-02-03")), + ShippingInfo[Sc](3, 2, LocalDate.parse("2012-05-06")) + ), + docs = "" + ) + } + test("map") { test("single") - checker( query = Text { Buyer.select.map(_.name) }, From 9d7bd6fe706f6164cbf7ef76d54a5027eccfcc37 Mon Sep 17 00:00:00 2001 From: NPCRUS Date: Thu, 27 Mar 2025 14:37:29 +0100 Subject: [PATCH 2/3] fix formatting --- scalasql/test/src/query/SelectTests.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scalasql/test/src/query/SelectTests.scala b/scalasql/test/src/query/SelectTests.scala index f74fd971..38b06194 100644 --- a/scalasql/test/src/query/SelectTests.scala +++ b/scalasql/test/src/query/SelectTests.scala @@ -178,7 +178,9 @@ trait SelectTests extends ScalaSqlSuite { test("filterOpt") { test("filter not added") - checker( - query = Text { ShippingInfo.select.filterOpt[Int](None)((value, table) => table.buyerId `=` value) }, + query = Text { + ShippingInfo.select.filterOpt[Int](None)((value, table) => table.buyerId `=` value) + }, sql = """ SELECT shipping_info0.id AS id, @@ -194,7 +196,9 @@ trait SelectTests extends ScalaSqlSuite { docs = "" ) test("filter added") - checker( - query = Text { ShippingInfo.select.filterOpt(Some(2))((value, table) => table.buyerId `=` value) }, + query = Text { + ShippingInfo.select.filterOpt(Some(2))((value, table) => table.buyerId `=` value) + }, sql = """ SELECT shipping_info0.id AS id, From a7a9524f614e5f44475ad08190ea5a752fa3772e Mon Sep 17 00:00:00 2001 From: NPCRUS Date: Thu, 27 Mar 2025 17:26:41 +0100 Subject: [PATCH 3/3] change params order in filterOpt --- docs/reference.md | 4 ++-- scalasql/query/src/Select.scala | 4 ++-- scalasql/query/src/SimpleSelect.scala | 4 ++-- scalasql/test/src/query/SelectTests.scala | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/reference.md b/docs/reference.md index 2a3db58c..c66c0bc5 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -805,7 +805,7 @@ ShippingInfo.select.filterIf(true)(_.buyerId `=` 2) ```scala -ShippingInfo.select.filterOpt[Int](None)((value, table) => table.buyerId `=` value) +ShippingInfo.select.filterOpt[Int](None)((table, value) => table.buyerId `=` value) ``` @@ -836,7 +836,7 @@ ShippingInfo.select.filterOpt[Int](None)((value, table) => table.buyerId `=` val ```scala -ShippingInfo.select.filterOpt(Some(2))((value, table) => table.buyerId `=` value) +ShippingInfo.select.filterOpt(Some(2))((table, value) => table.buyerId `=` value) ``` diff --git a/scalasql/query/src/Select.scala b/scalasql/query/src/Select.scala index 8b15701b..45d2b345 100644 --- a/scalasql/query/src/Select.scala +++ b/scalasql/query/src/Select.scala @@ -113,7 +113,7 @@ trait Select[Q, R] * if this option is Some[T] */ def filterOpt[T](option: Option[T])( - f: (T, Q) => Expr[Boolean] + f: (Q, T) => Expr[Boolean] ): Select[Q, R] /** @@ -346,7 +346,7 @@ object Select { override def filterIf(cond: Boolean)(f: Q => Expr[Boolean]): Select[Q, R] = selectToSimpleSelect().filterIf(cond)(f) - override def filterOpt[T](option: Option[T])(f: (T, Q) => Expr[Boolean]): Select[Q, R] = + override def filterOpt[T](option: Option[T])(f: (Q, T) => Expr[Boolean]): Select[Q, R] = selectToSimpleSelect().filterOpt(option)(f) override def aggregate[E, V](f: Aggregatable.Proxy[Q] => E)( diff --git a/scalasql/query/src/SimpleSelect.scala b/scalasql/query/src/SimpleSelect.scala index b177f79d..50f81243 100644 --- a/scalasql/query/src/SimpleSelect.scala +++ b/scalasql/query/src/SimpleSelect.scala @@ -98,9 +98,9 @@ class SimpleSelect[Q, R]( def filterIf(cond: Boolean)(f: Q => Expr[Boolean]): Select[Q, R] = if (cond) this.filter(f) else this - def filterOpt[T](option: Option[T])(f: (T, Q) => Expr[Boolean]): Select[Q, R] = option match { + def filterOpt[T](option: Option[T])(f: (Q, T) => Expr[Boolean]): Select[Q, R] = option match { case None => this - case Some(opt) => this.filter(q => f(opt, q)) + case Some(opt) => this.filter(q => f(q, opt)) } def join0[Q2, R2, QF, RF]( diff --git a/scalasql/test/src/query/SelectTests.scala b/scalasql/test/src/query/SelectTests.scala index 38b06194..8a26ef29 100644 --- a/scalasql/test/src/query/SelectTests.scala +++ b/scalasql/test/src/query/SelectTests.scala @@ -179,7 +179,7 @@ trait SelectTests extends ScalaSqlSuite { test("filterOpt") { test("filter not added") - checker( query = Text { - ShippingInfo.select.filterOpt[Int](None)((value, table) => table.buyerId `=` value) + ShippingInfo.select.filterOpt[Int](None)((table, value) => table.buyerId `=` value) }, sql = """ SELECT @@ -197,7 +197,7 @@ trait SelectTests extends ScalaSqlSuite { ) test("filter added") - checker( query = Text { - ShippingInfo.select.filterOpt(Some(2))((value, table) => table.buyerId `=` value) + ShippingInfo.select.filterOpt(Some(2))((table, value) => table.buyerId `=` value) }, sql = """ SELECT