protoquill-generic support

Library of generic CRUD operation for protoquill library. Only dynamic queries are supported.

It is used by: https://github.com/ajozwik/sbt-protoquill-crud-generic/

Maven Central Scala CI codecov Coverage Status

protoquill-generic is implementation for scala 3 project: quill-generic. protoquill-generic does not use macro yet. It used basic implementation for CRUD operations.

Purpose of CRUD operations - Repository - where F is monad

trait WithTransaction[F[_]] {
  def inTransaction[A](task: F[A]): F[A]
}

trait RepositoryWithGeneratedId[F[_], K, T <: WithId[K], UP] extends BaseRepository[F, K, T, UP] {
  def create(entity: T, generatedId: Boolean = true): F[K]

  def createAndRead(entity: T, generatedId: Boolean = true): F[T]

  def createOrUpdate(entity: T, generatedId: Boolean = true): F[K]

  def createOrUpdateAndRead(entity: T, generatedId: Boolean = true): F[T]
}

trait Repository[F[_], K, T <: WithId[K], UP] extends BaseRepository[F, K, T, UP] {
  def create(entity: T): F[K]

  def createAndRead(entity: T): F[T]

  def createOrUpdate(entity: T): F[K]

  def createOrUpdateAndRead(entity: T): F[T]
}

trait BaseRepository[F[_], K, T <: WithId[K], UP] {

  def all: F[Seq[T]]

  def read(id: K): F[Option[T]]

  def readUnsafe(id: K): F[T]

  def update(t: T): F[UP]

  def updateAndRead(t: T): F[T]
  def delete(id: K): F[UP]

  def deleteAll(): F[UP]

}

trait RepositoryWithTransaction[F[_], K, T <: WithId[K], UP] extends Repository[F, K, T, UP] with WithTransaction[F]

trait RepositoryWithTransactionWithGeneratedId[F[_], K, T <: WithId[K], UP] extends RepositoryWithGeneratedId[F, K, T, UP] with WithTransaction[F]

Because protoquill-macro's are created in compile time - we need to know primary key. Case class for database entity has to have field id - the primary key WithId If you have composite key you need to create case class like Cell4dId:

For table

CREATE TABLE IF NOT EXISTS CELL4D (
    `X`  INT NOT NULL,
    `Y`  INT NOT NULL,
    `Z`  INT NOT NULL,
    `T`  INT NOT NULL,
    `OCCUPIED` BOOLEAN,
    PRIMARY KEY (`X`, `Y`, `Z`, `T`)
)

Compose key can look like:

final case class Cell4dId(fk1: Int, fk2: Int, fk3: Int, fk4: Long) {
  def x: Int = fk1

  def y: Int = fk2

  def z: Int = fk3

  def t: Long = fk4

}

N-column is represented by fkN - and add schema-mapping:

implicit val meta: SchemaMeta[Cell4d] = schemaMeta[Cell4d]("CELL4D", _.id.fk1 -> "X", _.id.fk2 -> "Y", _.id.fk3 -> "Z", _.id.fk4 -> "T")

For more details look at sbt-protoquill-crud-generic