zio / zio-jdbc

A small, idiomatic ZIO interface to JDBC.
Apache License 2.0
82 stars 62 forks source link

Support `JdbcEncoder` when using `Segment.Param` #83

Open frekw opened 1 year ago

frekw commented 1 year ago

Hi!

I'm playing around with zio-jdbc together with Spanner, which natively supports raw bytes as a datatype.

I've declared a JdbcEncoder as follows:

  implicit val byteArrayjdbcEncoder: JdbcEncoder[Array[Byte]] =
    value => s"FROM_BASE64('${encoder.encodeToString(value)}')"

and that works greats togehter with .values. However, when I execute an update statement, e.g UPDATE foo SET bytes = $bytes WHERE id = $id my JdbcEncoder isn't being used, and I have to reimplement the same encoding as I do for inserts (likely because zio-jdbc doesn't check for the typeclass here). It would be really nice if zio-jdbc leverage the same JdbcEncoder I've already specified!

jdegoes commented 1 year ago

/bounty $50

algora-pbc[bot] commented 1 year ago

💎 $50 bounty • ZIO

Steps to solve:

  1. Start working: Comment /attempt #83 with your implementation plan
  2. Submit work: Create a pull request including /claim #83 in the PR body to claim the bounty
  3. Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts

Thank you for contributing to zio/zio-jdbc!

Add a bounty • Share on socials

Attempt Started (GMT+0) Solution
🟢 @andrzejressel #131
andrzejressel commented 1 year ago

Something like that in scope works fine:

        test("Custom JdbcEncoder") {
          implicit val byteArrayjdbcEncoder: JdbcEncoder[Array[Byte]] =
            value => s"FROM_BASE64('${Base64.getEncoder.encodeToString(value)}')"

          implicit def segmentFromJdbcEncoder[A](obj: A)(implicit encoder: JdbcEncoder[A]): Segment =
            Nested(encoder.encode(obj))

          val bytes = Array[Byte](1, 2, 3)

          val result = sql"UPDATE foo SET bytes = $bytes"

          assertTrue(
            result.toString == "Sql(UPDATE foo SET bytes = FROM_BASE64('AQID'))"
          )
        }

But having it in library itself causes a lot of errors due to implicit conversion ambiguity.

jdegoes commented 1 year ago

We can solve the implicit conversion ambiguity with implicit prioritization tricks (or something else...).

algora-pbc[bot] commented 1 year ago

💡 @andrzejressel submitted a pull request that claims the bounty. You can visit your org dashboard to reward.