Skip to content

Instantly share code, notes, and snippets.

@daddykotex
Created November 20, 2017 15:26
Show Gist options
  • Save daddykotex/271550f6c330269fc4fc245ca2ec0c65 to your computer and use it in GitHub Desktop.
Save daddykotex/271550f6c330269fc4fc245ca2ec0c65 to your computer and use it in GitHub Desktop.
If you have a SQL column that allows NULL but you want to fallback to a default rather than using an `Option[T]`, you can define your own composite like that. This is probably nota good way to do it but it works and avoid the throwing of `NonNullableColumnRead`
import java.sql.{ResultSet, PreparedStatement}
import doobie.enum.nullability.Nullable
import doobie.imports._
import doobie.util.meta
import doobie.util.meta.Meta
import doobie.util.kernel.Kernel
sealed trait LoginWay {
import LoginWay._
def asString: String = this match {
case UsernamePassword => "UsernamePassword"
case MicrosoftSSO => "MicrosoftSSO"
}
}
object LoginWay {
val DefaultValues: NonEmptyList[LoginWay] = NonEmptyList.nels(
UsernamePassword,
MicrosoftSSO
)
case object UsernamePassword extends LoginWay
case object MicrosoftSSO extends LoginWay
def parse(value: String): Option[LoginWay] = value match {
case "UsernamePassword" => Some(UsernamePassword)
case "MicrosoftSSO" => Some(MicrosoftSSO)
case _ => None
}
}
/**
https://github.com/tpolecat/doobie/blob/v0.4.4/yax/core/src/main/scala/doobie/util/meta.scala
https://github.com/tpolecat/doobie/blob/v0.4.4/yax/core/src/main/scala/doobie/util/kernel.scala
https://github.com/tpolecat/doobie/blob/v0.4.4/yax/core/src/main/scala/doobie/util/composite.scala
*/
implicit val loginWayComposite: Composite[NonEmptyList[LoginWay]] = {
val fromStr: String => NonEmptyList[LoginWay] = { str =>
Option(str)
.map(_.trim)
.map(_.split(",").toList.flatMap(x => LoginWay.parse(x.trim).toList))
.flatMap[NonEmptyList[LoginWay]](_.toNel)
.getOrElse(LoginWay.DefaultValues)
}
val toStr: NonEmptyList[LoginWay] => String = _.toList.map(_.asString).mkString(",")
val strMeta = Meta[String]
new Composite[NonEmptyList[LoginWay]] {
val kernel = new Kernel[NonEmptyList[LoginWay]] {
type I = NonEmptyList[LoginWay]
val ia = (i: I) => i
val ai = (a: I) => a
val get = (rs: ResultSet, n: Int) => {
val i = rs.getString(n)
if (rs.wasNull)
LoginWay.DefaultValues
else
fromStr(i)
}
val set = (ps: PreparedStatement, n: Int, nel: I) => {
strMeta.unsafeSetNonNullable(ps, n, toStr(nel))
}
val setNull = strMeta.unsafeSetNull _
val update = (rs: ResultSet, n: Int, nel: I) => {
strMeta.unsafeUpdateNonNullable(rs, n, toStr(nel))
}
val width = 1
}
val meta = List((strMeta, Nullable))
val toList = (a: NonEmptyList[LoginWay]) => List(a)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment