Skunk - Scala - Error with Multiple parameter query

I am getting an error with the code below

import br.com.gbtech.model.PaymentRequestItem
import cats.effect.{IO, Resource}
import skunk.codec.all.*
import skunk.implicits.*
import skunk.{Query, Session, ~}

  val query: Query[(String *: Int), ValueObject] =
    sql"""
      SELECT field1, field2
      FROM   sample_table
      WHERE  field1 = $text
      AND field2 = $int4
    """.query(ValueObject.decoder)

  database.use(s => s.option(query)((param1, param2)))

And the decoder is here:

case class ValueObject(field1: Int, field2: String)

object ValueObject {
  val decoder: Decoder[ValueObject] =
    (int4 ~ varchar).map { case (f1,  f2) => ValueObject(f1, f2) }
}

And the error is:

type mismatch;
 found   : skunk.Query[String *: Int *: org.typelevel.twiddles.EmptyTuple,br.com.ValueObject]
    (which expands to)  skunk.Query[String :: Int :: shapeless.HNil,br.com.ValueObject]
 required: skunk.Query[String *: Int,br.com.ValueObject]
    (which expands to)  skunk.Query[String :: Int,br.com.ValueObject]
        """.query(ValueObject.decoder)

Where is actually the problem?

Upvotes: 1

Views: 273

Answers (2)

Maftunbek
Maftunbek

Reputation: 13

Versions:

  • Skunk: 0.6.0
  • Cats: 2.10.0
  • Cats Effect: 3.4.8

Represents a Data Transfer Object (DTO) for a database entity

import skunk.codec.all.{int4, varchar}

object Dto {
/**
 * Represents a value object with two fields: field1 of type Int and 
 * field2 of type String. 
 */
case class ValueObject(field1: Int, field2: String)
 /**
 * Companion object for ValueObject, providing codecs for 
 * serialization/deserialization.
  */
  object ValueObject {
 /** Codec to serialize/deserialize ValueObject instances. */
    val codec: Codec[ValueObject] = (int4 *: varchar).to[ValueObject]
  }
}

This query has a slight error:


  val query: Query[(String *: Int), ValueObject] =
    sql"""
      SELECT field1, field2
      FROM   sample_table
      WHERE  field1 = $text
      AND field2 = $int4
    """.query(ValueObject.decoder)
  • WHERE field1 = $text AND field2 = $int4 should actually be field1 = $int4 and field2 = $text

  • Twiddle Lists String *: Int *: EmptyTuple use instead of tuple

import skunk._
import skunk.implicits._
import Dto._

object ValueObjectSql {
  val query: Query[String *: Int *: EmptyTuple, ValueObject] =
    sql"""
      SELECT field1, field2
      FROM sample_table
      WHERE field2 = $varchar
      AND field1 = $int4
    """.query(ValueObject.codec)
    }

Instead of s.option(query)((param1, param2)), please write s.option(query)(field2 *: field1 *: EmptyTuple).

import cats.effect.Resource
import cats.effect.kernel.MonadCancelThrow
import skunk._
import Dto._
import ValueObjectSql._

trait ValueObjectRepository[F[_]] {
  def findValue(field1: Int, field2: String): F[Option[ValueObject]]
}

object ValueObjectRepository {
  def make[F[_]: MonadCancelThrow](
      implicit
      session: Resource[F, Session[F]]
    ): ValueObjectRepository[F] = new ValueObjectRepository[F] {


    override def findValue(field1: Int, field2: String): F[Option[ValueObject]] =
      session.use(s => s.option(query)(field2 *: field1 *: EmptyTuple))
  }
}

Upvotes: 0

SOLUTION:

  • Fixing imports
import skunk.codec.all.*
import skunk.implicits.*
import skunk.*
  • Fixing Query type as explained here
Query[String *: Int *: EmptyTuple, ValueObject]
  • Fixing decoder
val decoder: Decoder[ValueObject] =
  (int4 ~ varchar).map { case (f1, f2) =>
    ValueObject(f1, f2) 
  }

Upvotes: 0

Related Questions