Skip to content

Instantly share code, notes, and snippets.

@TomTriple
Created November 12, 2016 14:37
Show Gist options
  • Save TomTriple/d64920c409b55c5ed5ca8f972f1e19fb to your computer and use it in GitHub Desktop.
Save TomTriple/d64920c409b55c5ed5ca8f972f1e19fb to your computer and use it in GitHub Desktop.
scala combinator library for db results
// 1. combinator library for transforming and combining sql results to query result models
// 2. usage of library resides at the bottom of this gist
package object mapping {
type Mapper[+A] = String => A
type ToValueClass[+A] = Long => A
type ToEnum[+A] = Int => A
case class Ops[+A](mapper: Mapper[A]) {
def optional() = _optional(mapper)
def map[B](f: A => B): Mapper[B] = _map(mapper)(f)
def flatMap[B](f: A => Mapper[B]): Mapper[B] = _flatMap(mapper)(f)
def log():Mapper[A] = _log(mapper)
def apply(on: String) = mapper.apply(on)
}
implicit def ops[A](a: Mapper[A]) = Ops(a)
def _log[A](mapper:Mapper[A]):Mapper[A] = { in =>
val result = mapper(in)
Log.d("MAPPING", "result is: " + result)
result
}
def enum[A](toEnum: ToEnum[A]):Mapper[A] = int().map(toEnum)
def controlactiontype():Mapper[ControlActionType.Value] = enum(ControlActionType.apply)
def inspectionstatus():Mapper[InspectionStatus.Value] = enum(InspectionStatus.apply)
def valueclass[A](toValueClass:ToValueClass[A]):Mapper[A] = long().map(toValueClass)
def playgroundId() = valueclass(PlaygroundId.apply)
def damageId() = valueclass(DamageId.apply)
def damagestatusId() = valueclass(DamageStatusId.apply)
def playobjectId() = valueclass(PlayobjectId.apply)
def controltaskId() = valueclass(ControltaskId.apply)
def damagetypeId() = valueclass(DamagetypeId.apply)
def inspectiontype() = enum(InspectionType.apply)
def inspectionobjectId() = valueclass(InspectionObjectId.apply)
def inspectionobjectdetailId() = valueclass(InspectionObjectDetailId.apply)
def controlobjecttypeId() = valueclass(ControlObjectTypeId.apply)
def inspectionId() = valueclass(InspectionId.apply)
def long(): Mapper[Long] = _.toLong
def int(): Mapper[Int] = _.toInt
def string(): Mapper[String] = in => in
def boolean(): Mapper[Boolean] = {
case "FALSE" | "0" => false
case "TRUE" | "1" => true
}
def double():Mapper[Double] = _.toDouble
def float():Mapper[Float] = _.toFloat
def date(): Mapper[java.sql.Date] = in => java.sql.Date.valueOf(in)
def timestamp(): Mapper[java.sql.Timestamp] = in => java.sql.Timestamp.valueOf(in)
def bytes():Mapper[Array[Byte]] = _.getBytes
def _optional[A](mapper: Mapper[A]): Mapper[Option[A]] = in => Option(in).map(mapper)
def _run[A](mapper: Mapper[A], on: String) = mapper(on)
def _map[A, B](mapper: Mapper[A])(f: A => B): Mapper[B] = _flatMap(mapper)(f.andThen(unit))
def unit[A](a: A): Mapper[A] = in => a
def _flatMap[A, B](mapper: Mapper[A])(f: A => Mapper[B]): Mapper[B] = { in =>
val value = mapper.apply(in)
f(value).apply(in)
}
class MappingString(str:String) {
def ->[T](mapper:Mapper[T]) = mapper.apply(str)
}
implicit def string2MappingString(str:String) = new MappingString(str)
import collection.JavaConversions._
private def results[T](results:GenericRawResults[T]):Seq[T] = {
results.getResults
}
private val dao = DaoInspection.getInstance()
object DB {
case class WrappedArray(values:Array[String]) {
def val0 = values(0)
def val1 = values(1)
def val2 = values(2)
def val3 = values(3)
def val4 = values(4)
def val5 = values(5)
def val6 = values(6)
}
def select[T](sql: String)(f: WrappedArray => T): Seq[T] = {
val result = dao.queryRaw(sql, new RawRowMapper[T] {
override def mapRow(columnNames: Array[String], values: Array[String]) = f(WrappedArray(values))
})
results(result)
}
def executeRaw(sql: String): Int = dao.executeRaw(sql)
def block[T](f: => T) = DbHelper.block(new Callable[T] {
def call(): T = f
})
def run[T](f: => T) = DbHelper.run(new Callable[T] {
def call(): T = f
})
def transaction[T](f: => T) = DbHelper.transaction(new Callable[T] {
def call():T = f
})
}
}
// usage of combinator library
def findOverview(playgroundId:PlaygroundId) = {
val sql =
s"""
select i.id, i.name, isc.duedate, insp.startdate is not null and insp.enddate is null as paused
from xxx i
left join xxx isc on isc.inspectiontype_id = i.id and isc.controlobject_id = ${playgroundId.get}
left join xxx insp on insp.controlobject_id = ${playgroundId.get} and insp.inspectiontype_id = i.id and insp.startdate is not null and insp.enddate is null
where i.moduleroottype = 1 and i.id <> 5
order by name
"""
DB.select(sql) { row =>
ControltypesOverviewDTO(
row.val0 -> inspectiontype(),
row.val1 -> string(),
row.val2 -> date().optional(),
row.val3 -> boolean()
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment