Skip to content

Commit

Permalink
Add MapToObject howto
Browse files Browse the repository at this point in the history
  • Loading branch information
sake92 committed Jan 9, 2024
1 parent 30aca07 commit 715ad1f
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 23 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Simple SQL queries in Scala 3.
No DSLs, no fuss, just plain SQL.

Supports *any* JDBC driver.
Additional support for Postgres, MySql, MariaDb, Oracle.
Additional support for Postgres, MySql, MariaDb, Oracle, H2.


---
Expand Down
2 changes: 0 additions & 2 deletions docs/src/files/howtos/HowToPage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package files.howtos
import utils.*
import Bundle.*

// TODO how to map flat result to List[stuff] groupByOrdered :)

trait HowToPage extends DocPage {

override def categoryPosts = List(
Expand Down
51 changes: 31 additions & 20 deletions docs/src/files/howtos/MapToObject.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,43 @@ object MapToObject extends HowToPage {
"How To Map Flat Rows To Objects",
frag(
s"""
You can do arbitrary SQL commands here.
The most common one is `UPDATE`-ing some rows:
Suppose you have these data `class`-es:
```scala
// returns number of affected rows
def updateCustomers: Int = ctx.run {
sql${Consts.tq}
UPDATE customers
SET name = 'whatever'
WHERE name LIKE 'xyz_%'
${Consts.tq}.update()
}
// table rows:
case class Customer(id: Int, name: String) derives SqlReadRow
case class Address(id: Int, name: String) derives SqlReadRow

// left join result:
case class CustomerWithAddressOpt(c: Customer, a: Option[Address]) derives SqlReadRow
```

---
Now, when you do a `SELECT` you'll get a `Seq[CustomerWithPhoneOpt]`, a "flat" result, named tuple.
But, on your REST API you'd like to return a structured object:
```scala
case class CustomerDTO(id: Int, name: String, addresses: Seq[String])
```

But of course you can do other commands as well:
Squery has utilities for exactly that.
Let's see how `groupByOrderedOpt` works:
```scala
def createTable: Unit = ctx.run {
sql${Consts.tq}
CREATE TABLE customers(
id SERIAL PRIMARY KEY,
name VARCHAR
)
${Consts.tq}.update()
}
import ba.sake.squery.utils.*

val groupedByCustomer: Map[Customer, Seq[Address]] = rowsLeftJoin.groupByOrderedOpt(_.c, _.a)
val dtos = groupedByCustomer.map { case (c, addresses) =>
CustomerDTO(c.id, c.name, addresses.map(_.name))
}.toSeq
```
We can see that it returns a `Map[Customer, Seq[Address]]`, just as we wanted.
Then we just map over it and populate the DTO object, can't be simpler!

---

This does a few thing for us:
- keeps the list of results *ordered*, so you don't have to sort it twice (once in DB, and again in memory)
- extracts the value that we need from the raw row result
- handles the `None` case
- handles the starting, empty Seq of results case


""".md
)
Expand Down
1 change: 1 addition & 0 deletions squery/test/src/ba/sake/squery/dataTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ba.sake.squery
import java.util.UUID
import java.time.Instant

// TODO remove street !?
case class Customer(id: Int, name: String, street: Option[String]) derives SqlReadRow:
def insertTuple = sql"(${name}, ${street})"

Expand Down
6 changes: 6 additions & 0 deletions squery/test/src/ba/sake/squery/utils/SeqUtilsSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class SeqUtilsSuite extends munit.FunSuite {

test("groupByOrderedOpt") {
val groupedByCustomer = rowsLeftJoin.groupByOrderedOpt(_.c, _.a)

val dtos = groupedByCustomer.map { case (c, addresses) =>
CustomerDTO(c.id, c.name, addresses.map(_.name.get))
}.toSeq
assertEquals(
groupedByCustomer,
Map(
Expand All @@ -63,4 +67,6 @@ class SeqUtilsSuite extends munit.FunSuite {
)
}

case class CustomerDTO(id: Int, name: String, addresses: Seq[String])

}

0 comments on commit 715ad1f

Please sign in to comment.