typelevel / doobie

Functional JDBC layer for Scala.
MIT License
2.17k stars 357 forks source link

Create a column name based result set mapper #752

Open Daenyth opened 6 years ago

Daenyth commented 6 years ago

As opposed to doobie's existing positional-only mapper.

@tpolecat If someone wanted to write and contribute this, what should they start looking at?

tpolecat commented 6 years ago

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.

wedens commented 6 years ago

I'd rather have ability to define column name based instances manually. Much easier to implement and harder for something to break.

YulawOne commented 6 years ago

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

antonyshchenko commented 6 years ago

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.

vasily802 commented 4 years ago

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 :'(

Daenyth commented 4 years ago

@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

tpolecat commented 4 years ago

You might look at the Quill integration, which works based on name.

chenjianjx commented 7 months ago

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 =  ...
     }
    ...
  }