Skip to content

Instantly share code, notes, and snippets.

@taku0
Created September 16, 2011 16:26
Show Gist options
  • Save taku0/1222477 to your computer and use it in GitHub Desktop.
Save taku0/1222477 to your computer and use it in GitHub Desktop.
オレオレJDBCラッパのプロトタイプ
import java.sql.ResultSet
import java.sql.PreparedStatement
import java.sql.Connection
import java.sql.Types
trait RowParser[A] extends ((ResultSet, Int) => A) {
def arity: Int
def apply(resultSet: ResultSet, index: Int): A
}
object RowParser {
implicit object IntParser extends RowParser[Int] {
def arity = 1
def apply(resultSet: ResultSet, index: Int) = {
resultSet.getInt(index)
}
}
implicit def functionToParser1[A1, R](f: A1 => R)(implicit parser1: RowParser[A1]): RowParser[R] = {
new RowParser[R] {
def arity = parser1.arity
def apply(resultSet: ResultSet, index: Int) = {
f(parser1(resultSet, index))
}
}
}
implicit def functionToParser2[A1, A2, R](f: (A1, A2) => R)(implicit parser1: RowParser[A1], parser2: RowParser[A2]): RowParser[R] = {
new RowParser[R] {
def arity = parser1.arity + parser2.arity
def apply(resultSet: ResultSet, index: Int) = {
f(parser1(resultSet, index),
parser2(resultSet, index + parser1.arity))
}
}
}
}
trait ParameterSetter {
def arity: Int
def setTo(index: Int, statement: PreparedStatement)
def setNull(index: Int, statement: PreparedStatement)
}
object ParameterSetter {
implicit def fromInt(value: Int): ParameterSetter = new ParameterSetter {
def arity = 1
def setTo(index: Int, statement: PreparedStatement) {
statement.setInt(index, value)
}
def setNull(index: Int, statement: PreparedStatement) {
statement.setNull(index, Types.INTEGER)
}
}
implicit def fromOption1[A1 <% ParameterSetter](option: Option[A1]): ParameterSetter = {
new ParameterSetter {
def arity = {
(null.asInstanceOf[A1]).arity
}
def setTo(index: Int, statement: PreparedStatement) = {
option match {
case Some(a1) => {
a1.setTo(index, statement)
}
case None => {
setNull(index, statement)
}
}
}
def setNull(index: Int, statement: PreparedStatement) = {
(null.asInstanceOf[A1]).setNull(index, statement)
}
}
}
implicit def fromOption2[A1 <% ParameterSetter, A2 <% ParameterSetter](option: Option[(A1, A2)]): ParameterSetter = {
new ParameterSetter {
def arity = {
(null.asInstanceOf[A1]).arity + (null.asInstanceOf[A2]).arity
}
def setTo(index: Int, statement: PreparedStatement) = {
option match {
case Some((a1, a2)) => {
a1.setTo(index, statement)
a2.setTo(index + a1.arity, statement)
}
case None => {
setNull(index, statement)
}
}
}
def setNull(index: Int, statement: PreparedStatement) = {
val a1 = null.asInstanceOf[A1]
val a2 = null.asInstanceOf[A2]
a1.setNull(index, statement)
a2.setNull(index + a1.arity, statement)
}
}
}
}
class RichConnection(connection: Connection) {
def queryIterable[A](sql: String, setters: ParameterSetter*)(implicit parser: RowParser[A]): Iterable[A] = {
val statement = connection.prepareStatement(sql)
try {
setParameters(statement, setters)
val resultSet = statement.executeQuery
val builder = Iterable.newBuilder[A]
while (resultSet.next()) {
builder += parser(resultSet, 1)
}
builder.result
} finally {
statement.close()
}
}
def executeUpdate[A](sql: String, setters: ParameterSetter*): Int = {
val statement = connection.prepareStatement(sql)
try {
setParameters(statement, setters)
statement.executeUpdate()
} finally {
statement.close()
}
}
protected def setParameters(statement: PreparedStatement, setters: Seq[ParameterSetter]) {
var index = 1
for (setter <- setters) {
setter.setTo(index, statement)
index += setter.arity
}
}
}
case class Foo(a: Int, b: Int)
object Foo {
implicit val parser: RowParser[Foo] = (apply _)
implicit def toSetter(foo: Foo): ParameterSetter = unapply(foo)
}
case class Bar(a: Foo, b: Int)
object Bar {
implicit val parser = (apply _): RowParser[Bar]
implicit def toSetter(bar: Bar): ParameterSetter = unapply(bar)
}
case class Buz(a: Int, b: Bar)
object Buz {
implicit val parser = (apply _): RowParser[Buz]
implicit def toSetter(buz: Buz): ParameterSetter = unapply(buz)
}
object Main extends App {
println(implicitly[RowParser[Buz]].arity)
println((null.asInstanceOf[Buz]).arity)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment