0

I got a doobie query that doesn't want to compile:

package de.x.vmdbplanningvalues.impl.queries import de.x.campaignplans.CampaignPlanId import de.x.distributionbrands.DistributionBrandId import de.x.vmdbplanningvalues._ import doobie._ object UpdateVmdbPlanningValuesQuery { case class VmdbPlanningUpdate( creditRatingRejections: Option[Double], goodsCoupons: Option[Double], customerDiscounts: Option[Double], campaignPlanId: String, distributionBrandId: String, country: String, categoryId: String, lane: VmdbLane ) def apply( distributionBrand: DistributionBrandId, country: String, campaignPlanId: CampaignPlanId, category: String, updates: List[VmdbPlanningValuesForVmdbLane] ): ConnectionIO[Unit] = { for { _ <- updateQuery(updates.map(update => VmdbPlanningUpdate( update.creditRatingRejections, update.goodsCoupons, update.customerDiscounts, campaignPlanId.id, distributionBrand.id, country, category, update.lane ) )) } yield () } def updateQuery[T: Write](updates: List[VmdbPlanningUpdate]): ConnectionIO[Int] = { val sql = """ UPDATE vmdb_planning_values as vmdb SET vmdb.credit_rating_rejections = ?, vmdb.goods_coupons = ?, vmdb.customer_discounts = ? FROM campaign_plan cp WHERE cp.id = ? AND vmdb.distribution_brand_id = ? AND vmdb.country_id = ? AND vmdb.year=DATE_PART('year', cp.start_date) AND vmdb.quarter=DATE_PART('quarter', cp.start_date) AND vmdb.category_id = ? AND vmdb.lane = ? """ Update[VmdbPlanningUpdate](sql).updateMany(updates) } } 

However it fails with the following error:

[error] /Users/johannesklauss/Documents/campaign-service/server/src/main/scala/de/x/vmdbplanningvalues/impl/queries/UpdateVmdbPlanningValuesQuery.scala:60:35: could not find implicit value for parameter W: doobie.Write[de.x.vmdbplanningvalues.impl.queries.UpdateVmdbPlanningValuesQuery.VmdbPlanningUpdate] [error] Update[VmdbPlanningUpdate](sql).updateMany(updates) [error] 

I am not quite sure what the error message means, since I am still a bit fuzzy about implicits in Scala. Does anybody have an idea?

Edit: Added VmdbLane.scala:

package de.x.vmdbplanningvalues import io.circe.Decoder.Result import io.circe._ sealed trait VmdbLane { override def toString: String = VmdbLane.toEnum(this) } object VmdbLane { case object New extends VmdbLane case object CarryOver extends VmdbLane case object Sale extends VmdbLane case object Sum extends VmdbLane def toEnum(e: VmdbLane): String = e match { case New => "new" case CarryOver => "carryOver" case Sale => "sale" case Sum => "sum" } def fromEnum(s: String): Option[VmdbLane] = Option(s) collect { case "new" => New case "carryOver" => CarryOver case "sale" => Sale case "sum" => Sum } implicit val jsonFormat: Encoder[VmdbLane] with Decoder[VmdbLane] = new Encoder[VmdbLane] with Decoder[VmdbLane] { override def apply(a: VmdbLane): Json = Encoder.encodeString(toEnum(a)) override def apply(c: HCursor): Result[VmdbLane] = c.value.asString.flatMap(s => fromEnum(s)) match { case Some(a) => Right(a) case None => Left(DecodingFailure("VmdbLane", c.history)) } } } 
3
  • @EmilianoMartinez Aren't those case objects the implementations? case object New extends VmdbLane case object CarryOver extends VmdbLane case object Sale extends VmdbLane case object Sum extends VmdbLane Commented Nov 2, 2022 at 11:55
  • You probably need to add some custom Writes instance for the enum just like you did with the circe ones - BTW, rather than Decoder with Encoder you can use Codec for circe. Commented Nov 2, 2022 at 12:14
  • Yes they are implementations, I didn´t read carefully... Commented Nov 2, 2022 at 12:18

1 Answer 1

1

The problem was not related to Circe it is related to how the custom doobie type mapping works. If you include something like inside the VmdbLane object:

implicit val natGet: Get[VmdbLane] = Get[String].map(in => { in match { case "New" => New case "CarryOver" => CarryOver case "Sale" => Sale case "Sum" => Sum } }) implicit val natPut: Put[VmdbLane] = Put[String].contramap { case New => "New" case CarryOver => "CarryOver" case Sale => "Sale" case Sum => "Sum" } 

The compiler should include the mapping an it should work.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.