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)) } } }
case object New extends VmdbLanecase object CarryOver extends VmdbLanecase object Sale extends VmdbLanecase object Sum extends VmdbLaneWritesinstance for the enum just like you did with the circe ones - BTW, rather thanDecoder with Encoderyou can useCodecfor circe.