Friday, July 19, 2019

Woobie Doobie - switching database access library in Scala

Doobie is getting more and more popular as a database access tool in modern applications. This year on Scalar conference voting Doobie won over its competition - particularly Slick. Not without a reason. Recently my project also dropped Slick.
Doobie gave us nearly immediately:
  • easier learning curve - it is about plain, old SQL ;
  • more compile time verification - now you do not need to run your query to find out your type mapping is broken ;
  • referential transparency and better integration with effects system used in project ;
  • no hacking needed when you need to select more columns than unfamous 22. One particular issue that came out quite early was a bit tricky to resolve with given message:
    [error] Cannot construct a parameter vector of the following type:
    [error]
    [error]   Boolean(true) :: shapeless.HNil
    [error]
    [error] Because one or more types therein (disregarding HNil) does not have a Put
    [error] instance in scope. Try them one by one in the REPL or in your code:
    [error]
    [error]   scala> Put[Foo]
    [error]
    [error] and find the one that has no instance, then construct one as needed. Refer to
    [error] Chapter 12 of the book of doobie for more information.
    
    Studying chapter 12 did not help. Here is the query that caused the issue:
    sql"select one_col, two_col from TABLE where flag = ${true} "
    
    It turns out that Doobie (actually Shapeless) does not handle properly the inlined true literal. What is needed is just to extract it to separate value:
    val flag = true
    sql"select one_col, two_col from TABLE where flag = ${flag} "
    
    That resolves the problem. It would also work if we added type annotation:
    sql"select one_col, two_col from TABLE where flag = ${true: Boolean} "
    
    It's up to you which way you prefer.