Skip to content

Instantly share code, notes, and snippets.

@Timshel
Last active April 9, 2018 10:13
Show Gist options
  • Save Timshel/98d89f27221fb0bceb94219aa829b07d to your computer and use it in GitHub Desktop.
Save Timshel/98d89f27221fb0bceb94219aa829b07d to your computer and use it in GitHub Desktop.
Doobie Raw sql interpolation
import doobie.util.param.Param
import doobie.util.pos.Pos
/**
* Custom Interpolator with support for raw sql.
* `Composite.toList` is used retrieve and insert raw sql.
*/
final class RawSqlInterpolator(private val sc: StringContext)(implicit pos: Pos) {
private def mkFragment[A](a: A)(implicit ev: Param[A]): Fragment = {
val interleave = ev.composite.toList(a).map {
case SiteListTable.RawSql(sql) => sql
case _ => "?"
}
val sql = sc.parts
.zipAll(interleave, "", "")
.map { case (a, b) => a + b }
.mkString("")
Fragment(sql, a, Some(pos))(ev.composite)
}
object frRaw extends ProductArgs {
def applyProduct[A: Param](a: A): Fragment = mkFragment(a)
}
}
object RawSqlInterpolator {
import doobie.imports._
case class RawSql(value: String)
/**
* This is an empty composite (length 0, empty Meta).
* The RawSql is exposed using `toList` which in the latest version is only used for logging.
* (Cf: https://github.com/tpolecat/doobie/blob/series/0.5.x/modules/core/src/main/scala/doobie/util/composite.scala#L43)
*/
trait RawSqlComposite[T] extends doobie.util.composite.Composite[T]{
val length: Int = 0
val meta: List[(doobie.util.meta.Meta[_], doobie.enum.nullability.NullabilityKnown)] = Nil
val set: (Int, T) => doobie.free.preparedstatement.PreparedStatementIO[Unit] ={
(n, a) => FPS.raw( ps => () )
}
val update: (Int, T) => doobie.free.resultset.ResultSetIO[Unit] = {
(n, a) => FRS.raw( rs => () )
}
}
val rawSqlComposite = new RawSqlComposite[RawSql] {
def toList(sql: RawSql): List[Any] = List(sql)
val unsafeGet: (java.sql.ResultSet, Int) => RawSql = { (_, _) => RawSql("NO GET ON RawSql") }
}
def rawSqlComposite[T](t: T, sql: String) = new RawSqlComposite[T] {
def toList(a: T): List[Any] = List(RawSql(sql))
val unsafeGet: (java.sql.ResultSet, Int) => T = { (_, _) => t }
}
implicit val rawSqlParam = new doobie.util.param.Param(rawSqlComposite)
implicit def rawSqlInterpolator(sc: StringContext)(implicit pos: Pos): RawSqlInterpolator = new RawSqlInterpolator(sc)(pos)
}
object SiteListTable {
import doobie.imports._
import RawSqlInterpolator._
val tableName = RawSql("site_list")
def selectQuery(ioId: IOId): Update0 = frRaw"""
SELECT * FROM $tableName WHERE io_id = $ioId
""".query[SiteList]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment