-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace Schema-based derivation of encoder / decoder with ZIO Schema Deriver-based derivation #144
Comments
/bounty $250 |
💎 $250 bounty • ZIOSteps to solve:
Additional opportunities:
Thank you for contributing to zio/zio-jdbc! Add a bounty • Share on socials
|
Hi, I'd like to try this one /attempt #144 |
@FVelasquezM: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then 🙏 |
The bounty is up for grabs! Everyone is welcome to |
I have been playing with this for a few hours but my lack of experience with zio-schema shows and I could not find non-trivial examples of using
Thank you. val drv: Deriver[JdbcDecoder] = new Deriver[JdbcDecoder] {
override def deriveRecord[A](
record: Schema.Record[A],
fields: => Chunk[WrappedF[zio.jdbc.JdbcDecoder, ?]],
summoned: => Option[JdbcDecoder[A]]
): JdbcDecoder[A] =
new JdbcDecoder[A] {
override def unsafeDecode(columnIndex: Int, rs: ResultSet): (Int, A) = {
val (nextColumn, fieldValues) = fields
.foldLeft((columnIndex, Chunk.empty[Any])) { case ((col, values), decoder) =>
decoder
.unwrap
.decode(col, rs) // 1
.fold(
e => throw new JdbcDecoderError("Cannot decode value", e, rs.getMetaData(), rs.getRow()),
(c, value) => (c + 1, values :+ value)
)
}
Unsafe
.unsafe(record.construct(fieldValues)) // 2
.fold(
e => throw new JdbcDecoderError("Cannot construct record", new Exception(e), rs.getMetaData(), rs.getRow()),
a => (nextColumn - 1, a)
)
}
}
…
}.autoAcceptSummoned
case class User(name: String, age: Int)
case class Id(value: Int)
case class Rec(id: Int, user: User, id2: Id)
given Schema[Rec] = DeriveSchema.gen
given JdbcDecoder[Rec] = Derive.derive(drv)
// query
sql"SELECT id, name, age, id * 2 FROM users".query[Rec].selectAll
/*
Rec(1, User(Pierre, 100), Id(2))
Rec(2, User(John, 20), Id(4))
Rec(3, User(Nelly, 17), Id(6))
*/
// with custom decoder of inner record
given JdbcDecoder[Id] = JdbcDecoder.intDecoder.map(n => Id(n + 1000))
/*
Rec(1, User(Pierre, 100), Id(1002))
Rec(2, User(John, 20), Id(1004))
Rec(3, User(Nelly, 17), Id(1006))
*/ |
My further experiments and attempts to use zio-jdbc in one of my projects bring me to another question: should the codecs work based on position or names? As for now, they seem to work based on names for records (case classes). This has issue with nested case classes (how to name columns in result set and how to refer to nested values). My attempt above uses positional decoding, I think the example I provided would not be possible with name-based decoding. |
/attempt #144
|
@Andrapyre: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then 🙏 |
The bounty is up for grabs! Everyone is welcome to |
Currently, ZIO JDBC directly converts from Schema to encoders / decoders by generating the appropriate type class instances (JdbcEncoder, JdbcDecoder).
This is not ideal, because it means a user does not have any ability to define a custom encoder / decoder for any part of their ADT.
In order to solve this problem, we can switch from defining
Schema => Decoder / Encoder
, and instead use theDeriver
mechanism built into ZIO Schema, which is designed to solve this precise problem.Using
Deriver
to derive JdbcEncoder / JdbcDecoder, we can both automatically support derivation, as well as allow user-defined overrides for parts of a larger data type.The text was updated successfully, but these errors were encountered: