doobie
doobie copied to clipboard
Create a column name based result set mapper
As opposed to doobie's existing positional-only mapper.
@tpolecat If someone wanted to write and contribute this, what should they start looking at?
In terms of the 0.6 API Get
and Put
will need methods that take column names (easy) and Read
and Write
will need derivations based on NamedGeneric
to make them aware of field names. You'll also probably need a strategy for dealing with renames … camelcase to snake case, etc. And we'll need a way to deal with prioritization of structural vs. name-based derivations, possibly by switching to a semi-automatic strategy like Circe has.
I'd rather have ability to define column name based instances manually. Much easier to implement and harder for something to break.
I was working on schema support for doobie concept, which I was planning to evolve into some slick like DSL for doobie. Maybe you'll find interesting the idea. https://gist.github.com/YulawOne/736764054a5e9dfda03e7ffb398f8efd
For me a manual mapping would be already useful. Currently I'm using ScalikeJDBC
with mapping defined like this:
private def authorityFromRs(rs: WrappedResultSet): Authority =
Authority(
rs.long("id"),
rs.string("name"),
rs.string("description")
)
where Authority
is my model case class.
That's boilerplate of course, but it's easy to understand and implement. An ability to have such a simple manual mapping for cases where automatic derivation is not convenient would make doobie
more approachable in my opinion.
Is there really still no way to set mapping based on column names? That's a deal breaker. I have to resort to scalikejdbc now :'(
@vasily802 It's possible to do it, it just isn't built into the library. Ask on gitter, I don't know who has the code but it's also possible to write on your own
For one example of name-based derivation (for another library), one could consult Cormorant
's LabelledRead
, which performs the equivalent row decode operation for CSV inputs. https://github.com/ChristopherDavenport/cormorant/blob/master/modules/generic/src/main/scala/io/chrisdavenport/cormorant/generic/semiauto.scala#L40
You might look at the Quill integration, which works based on name.
For whoever needs this, there is workaround using low-level api. You can do it by referring to https://github.com/tpolecat/doobie/blob/dc960d95654c6580725b6b2146df3389dcae5a2d/modules/example/src/main/scala/example/FreeUsage.scala#L45
You can implement it like
l <- FPS.executeQuery.bracket { rs =>
FPS.embed(rs, FRS.raw {resultSetToRecords})
} (FPS.embed(_, FRS.close))
...
def resultSetToRecords(rs: ResultSet): List[YourRecord] = {
while (rs. next()) {
val yourRecord = ...
}
...
}