ldbc.dsl.ResultSetConsumer.scala Maven / Gradle / Ivy
/**
* Copyright (c) 2023-2024 by Takahiko Tominaga
* This software is licensed under the MIT License (MIT).
* For more information see LICENSE or https://opensource.org/licenses/MIT
*/
package ldbc.dsl
import cats.*
import cats.syntax.all.*
import ldbc.sql.ResultSet
import ldbc.dsl.util.FactoryCompat
import ldbc.dsl.codec.Decoder
/**
* Trait for generating the specified data type from a ResultSet.
*
* @tparam F
* The effect type
* @tparam T
* Type you want to build with data obtained from ResultSet
*/
trait ResultSetConsumer[F[_], T]:
/**
* Method for generating the specified data type from a ResultSet.
*
* @param resultSet
* A table of data representing a database result set, which is usually generated by executing a statement that
* queries the database.
* @return
* Type you want to build with data obtained from ResultSet
*/
def consume(resultSet: ResultSet): F[T]
object ResultSetConsumer:
type Read[T] = ResultSet => T
given [F[_]: Monad, T](using
consumer: ResultSetConsumer[F, Option[T]],
error: MonadError[F, Throwable]
): ResultSetConsumer[F, T] with
override def consume(resultSet: ResultSet): F[T] =
consumer.consume(resultSet).flatMap {
case Some(value) => error.pure(value)
case None => error.raiseError(new NoSuchElementException(""))
}
given [F[_]: Monad, T](using decoder: Decoder[T]): ResultSetConsumer[F, Option[T]] with
override def consume(resultSet: ResultSet): F[Option[T]] =
if resultSet.next() then Monad[F].pure(decoder.decode(resultSet, None).some) else Monad[F].pure(None)
given [F[_]: Monad, T, G[_]](using
decoder: Decoder[T],
factoryCompat: FactoryCompat[T, G[T]]
): ResultSetConsumer[F, G[T]] with
override def consume(resultSet: ResultSet): F[G[T]] =
val builder = factoryCompat.newBuilder
while resultSet.next() do builder += decoder.decode(resultSet, None)
Monad[F].pure(builder.result())