Skip to content

Commit

Permalink
Add more DAO utils
Browse files Browse the repository at this point in the history
  • Loading branch information
sake92 committed Aug 24, 2024
1 parent c273a15 commit b9b0428
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 34 deletions.
13 changes: 3 additions & 10 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@

- allow unambiguous colprefix.col1,
handy when joining with other table, but returning only it

- camelcase setting inline vals in generator

- parametrize mill plugin

- find/update/delete where DAO functions

- override types

- paging
https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html


- batching ?

- start temp mujz/pagila in CI with docker
- generate pagila files with mill plugin
Expand Down
73 changes: 62 additions & 11 deletions generator/src/ba/sake/squery/generator/SqueryGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,31 @@ class SqueryGenerator(ds: DataSource, config: SqueryGeneratorConfig = SqueryGene
else s"${pkCol.metadata.name} = $${id}"
}

def genCountAllQuery: String =
def genCountAll: String =
s"""| def countAll(): DbAction[Int] =
| sql"SELECT COUNT(*) FROM $${${caseClassName}.tableName}".readValue()
|""".stripMargin
def genFindAllQuery: String =
def genCountWhere: String =
s"""| def countWhere(whereQuery: Query): DbAction[Int] =
| sql"SELECT COUNT(*) FROM $${${caseClassName}.tableName} WHERE $${whereQuery}".readValue()
|""".stripMargin

def genFindAll: String =
s"""| def findAll(): DbAction[Seq[${caseClassName}]] =
| sql"SELECT $${${caseClassName}.allCols} FROM $${${caseClassName}.tableName}".readRows()
|""".stripMargin

def genFindWhere: String =
s"""| def findWhere(whereQuery: Query): DbAction[${caseClassName}] =
| sql"SELECT $${${caseClassName}.allCols} FROM $${${caseClassName}.tableName} WHERE $${whereQuery}".readRow()
|""".stripMargin
def genFindWhereOpt: String =
s"""| def findWhereOpt(whereQuery: Query): DbAction[Option[${caseClassName}]] =
| sql"SELECT $${${caseClassName}.allCols} FROM $${${caseClassName}.tableName} WHERE $${whereQuery}".readRowOpt()
|""".stripMargin
def genFindAllWhere: String =
s"""| def findAllWhere(whereQuery: Query): DbAction[Seq[${caseClassName}]] =
| sql"SELECT $${${caseClassName}.allCols} FROM $${${caseClassName}.tableName} WHERE $${whereQuery}".readRows()
|""".stripMargin
def genFindById: Option[String] = Option.when(tableDef.hasPk) {
val whereExpr = byIdWhereExpr("id")
s"""| def findById(id: ${caseClassName}.PK): DbAction[${caseClassName}] =
Expand All @@ -200,6 +216,13 @@ class SqueryGenerator(ds: DataSource, config: SqueryGeneratorConfig = SqueryGene
| sql"SELECT $${${caseClassName}.allCols} FROM $${${caseClassName}.tableName} WHERE ${whereExpr}".readRowOpt()
|""".stripMargin
}
def genFindByIds: Option[String] = Option.when(tableDef.hasPk && !tableDef.hasCompositePk) {
s"""| def findByIds(ids: Set[${caseClassName}.PK]): DbAction[Seq[${caseClassName}]] =
| val idsExpr = ids.map(id => sql"$${id}").reduce(_ ++ sql"," ++ _)
| sql"SELECT $${${caseClassName}.allCols} FROM $${${caseClassName}.tableName} WHERE ${tableDef.pkColumns.head.metadata.name} IN ($${idsExpr})".readRows()
|""".stripMargin
}

def genInsert: String = {
// TODO if cols are autoinc
// https://www.jooq.org/doc/latest/manual/sql-building/sql-statements/insert-statement/insert-returning/
Expand All @@ -218,21 +241,22 @@ class SqueryGenerator(ds: DataSource, config: SqueryGeneratorConfig = SqueryGene
| ""\".insertReturningRow()
|""".stripMargin
else
s"""| def insert(row: ${caseClassName}): DbAction[Unit] =
s"""| def insert(row: ${caseClassName}): DbAction[Int] =
| sql""\"
| INSERT INTO $${${caseClassName}.tableName}($${${caseClassName}.allCols})
| VALUES(${insertExpr})
| ""\".insert()
|""".stripMargin
}

def genUpdateById: Option[String] = Option.when(tableDef.hasPk) {
val updateExpr = tableDef.nonPkColDefs
.map { colDef =>
s" ${colDef.metadata.name} = $${row.${colDef.metadata.name.safeName}}"
}
.mkString(",\n")
val whereExpr = byIdWhereExpr("row")
s"""| def updateById(row: ${caseClassName}): DbAction[Unit] =
s"""| def updateById(row: ${caseClassName}): DbAction[Int] =
| sql""\"
| UPDATE $${${caseClassName}.tableName}
| SET
Expand All @@ -241,34 +265,61 @@ class SqueryGenerator(ds: DataSource, config: SqueryGeneratorConfig = SqueryGene
| ""\".update()
|""".stripMargin
}

def genDeleteWhere: String =
s"""| def deleteWhere(whereQuery: Query): DbAction[Int] =
| sql"DELETE FROM $${${caseClassName}.tableName} WHERE $${whereQuery}".update()
|""".stripMargin
def genDeleteById: Option[String] = Option.when(tableDef.hasPk) {
val whereExpr = byIdWhereExpr("id")
s"""| def deleteById(id: ${caseClassName}.PK): DbAction[Unit] =
s"""| def deleteById(id: ${caseClassName}.PK): DbAction[Int] =
| sql"DELETE FROM $${${caseClassName}.tableName} WHERE ${whereExpr}".update()
|""".stripMargin
}
def genDeleteByIds: Option[String] = Option.when(tableDef.hasPk && !tableDef.hasCompositePk) {
s"""| def deleteIds(ids: Set[${caseClassName}.PK]): DbAction[Int] =
| val idsExpr = ids.map(id => sql"$${id}").reduce(_ ++ sql"," ++ _)
| sql"DELETE FROM $${${caseClassName}.tableName} WHERE ${tableDef.pkColumns.head.metadata.name} IN ($${idsExpr})".update()
|""".stripMargin
}

// must have a PK to work
val optionalSelectQueries = Seq(
genFindById,
genFindByIdOpt
genFindByIdOpt,
genFindByIds
).flatten.mkString("\n")
val optionalUpdateQueries = Seq(
genUpdateById,
genDeleteById
genUpdateById
).flatten.mkString("\n")
val optionalDeleteQueries = Seq(
genDeleteById,
genDeleteByIds
).flatten.mkString("\n")

val contents =
s"""|trait ${daoClassName} {
|${genCountAllQuery}
|${genCountAll}
|
|${genCountWhere}
|
|${genFindAllQuery}
|${genFindAll}
|
|${genFindWhere}
|
|${genFindWhereOpt}
|
|${genFindAllWhere}
|
|${optionalSelectQueries}
|
|${genInsert}
|
|${optionalUpdateQueries}
|
|${genDeleteWhere}
|
|${optionalDeleteQueries}
|}
|
|object ${daoClassName} extends ${daoClassName}
Expand Down
77 changes: 77 additions & 0 deletions mill-plugin-itest/src/h2/root/test/src/ActorCrudDaoSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package public

import java.time.*
import ba.sake.squery.{*, given}
import public.models.*
import public.daos.*

class ActorCrudDaoSuite extends munit.FunSuite {

val matthewRows = Seq(
ActorRow(
ACTOR_ID = 8,
FIRST_NAME = "MATTHEW",
LAST_NAME = "JOHANSSON",
LAST_UPDATE = LocalDateTime.parse("2006-02-15T04:34:33")
),
ActorRow(
ACTOR_ID = 103,
FIRST_NAME = "MATTHEW",
LAST_NAME = "LEIGH",
LAST_UPDATE = LocalDateTime.parse("2006-02-15T04:34:33")
),
ActorRow(
ACTOR_ID = 181,
FIRST_NAME = "MATTHEW",
LAST_NAME = "CARREY",
LAST_UPDATE = LocalDateTime.parse("2006-02-15T04:34:33")
)
)

test("ActorCrudDao should work as expected") {
Globals.ctx.run {
/* count */
val totalCount = ActorCrudDao.countAll()
assertEquals(totalCount, 200)

val matthewsCount = ActorCrudDao.countWhere(sql"${ActorRow.firstName} = 'MATTHEW'")
assertEquals(matthewsCount, 3)

/* find */
val matthews = ActorCrudDao.findAllWhere(sql"${ActorRow.firstName} = 'MATTHEW'")
assertEquals(matthews, matthewRows)

val matthewJohansson =
ActorCrudDao.findWhere(sql"${ActorRow.firstName} = 'MATTHEW' AND ${ActorRow.lastName} = 'JOHANSSON'")
assertEquals(matthewJohansson, matthewRows(0))

val matthewJohanssonById = ActorCrudDao.findById(8)
assertEquals(matthewJohanssonById, matthewRows(0))

val matthewsByIds = ActorCrudDao.findByIds(Set(8, 103))
assertEquals(matthewsByIds, matthewRows.take(2))

/* insert */
val newMatthew = ActorRow(
ACTOR_ID = 203,
FIRST_NAME = "MATTHEW",
LAST_NAME = "MATTHEWEWICH",
LAST_UPDATE = LocalDateTime.parse("2006-02-15T04:34:33")
)
ActorCrudDao.insert(newMatthew)
val newMatthewInserted = ActorCrudDao.findById(newMatthew.ACTOR_ID)
assertEquals(newMatthewInserted, newMatthew)

/* upadte */
val updateMatthew = newMatthew.copy(LAST_NAME = "MATTHEWROLOMEU")
ActorCrudDao.updateById(updateMatthew)
val newMatthewUpdated = ActorCrudDao.findById(newMatthew.ACTOR_ID)
assertEquals(newMatthewUpdated, updateMatthew)

/* delete */
ActorCrudDao.deleteById(newMatthew.ACTOR_ID)
val newMatthewOpt = ActorCrudDao.findByIdOpt(newMatthew.ACTOR_ID)
assertEquals(newMatthewOpt, None)
}
}
}
5 changes: 3 additions & 2 deletions mill-plugin-itest/src/h2/root/test/src/Globals.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ba.sake.squery.{*, given}
import public.daos.*
package public

import ba.sake.squery.SqueryContext

object Globals {
private val ds = new com.zaxxer.hikari.HikariDataSource()
Expand Down
13 changes: 2 additions & 11 deletions squery/src/ba/sake/squery/write/SqlWrite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,8 @@ object SqlWrite {
idx: Int,
valueOpt: Option[LocalDateTime]
): Unit = valueOpt match
case Some(value) =>
ps.setDate(
idx,
java.sql.Date(
value
.atZone(ZoneId.systemDefault())
.toInstant()
.toEpochMilli()
)
)
case None => ps.setNull(idx, jsql.Types.TIMESTAMP)
case Some(value) => ps.setObject(idx, value)
case None => ps.setNull(idx, jsql.Types.TIMESTAMP)
}

given SqlWrite[Array[Byte]] with {
Expand Down

0 comments on commit b9b0428

Please sign in to comment.