moved the jdbc string template API out of the test case :) and fix up some cruft in the API docs

This commit is contained in:
James Strachan
2012-03-14 20:44:54 +00:00
parent 4352ed38e5
commit 7137872ede
4 changed files with 187 additions and 171 deletions
@@ -1,6 +1,8 @@
package kotlin.jdbc
import java.sql.*
import kotlin.template.StringTemplate
import java.math.BigDecimal
/**
* Helper method to process a statement on this collection
@@ -21,6 +23,15 @@ fun Connection.update(sql: String): Int {
return statement{ it.executeUpdate(sql) }
}
/**
* Performs the SQL update using the [[StringTemplate]]
*/
fun Connection.update(template : StringTemplate) : Int {
val preparedStatement = prepare(template)
return preparedStatement.update()
}
/**
* Perform a query on the connection and processes the result set with a function
*/
@@ -33,4 +44,158 @@ fun <T> Connection.query(sql: String, block: (ResultSet) -> T): T {
throw IllegalStateException("No ResultSet returned executeQuery($sql) on $this")
}
}
}
}
/**
* Perform a query on the connection using the [[StringTemplate]] to generate the SQL text
* and processes the result set with a function
*/
fun <T> Connection.query(template : StringTemplate, resultBlock : (ResultSet) -> T) : T {
val preparedStatement = prepare(template)
return preparedStatement.query(resultBlock)
}
/**
* Creates a [[PreparedStatement]] from the [[StringTemplate]]
*/
fun Connection.prepare(template : StringTemplate) : PreparedStatement {
val builder = PreparedStatementBuilder(template, this)
builder.bind()
return builder.statement
}
class PreparedStatementBuilder(val template : StringTemplate, val connection : Connection) {
private var parameterIndex = 0
public val sql : String = createSql()
public val statement: PreparedStatement = lookupOrCreateStatement()
/**
* Binds the values in the [[StringTemplate]] to the [[PreparedStatement]]
*/
fun bind() {
var constantText = true
template.forEach{
if (!constantText) {
expression(it)
}
constantText = !constantText
}
}
fun expression(value : Any?) : Unit {
// TODO causes compiler error
// if (value is Number) {
if (value is Int) {
expression(value)
} else if (value is Double) {
expression(value)
} else if (value is Float) {
expression(value)
} else if (value is BigDecimal) {
expression(value)
} else if (value is Byte) {
expression(value)
} else if (value is Long) {
expression(value)
} else if (value is Short) {
expression(value)
/*
} else {
expression(value.toDouble())
}
*/
}
else if (value is String) {
expression(value)
} else if (value is ByteArray) {
expression(value)
} else if (value is Date) {
expression(value)
} else if (value is Time) {
expression(value)
} else if (value is Timestamp) {
expression(value)
} else {
statement.setObject(nextParameterIndex(), value)
}
}
fun expression(value : String?) : Unit {
statement.setString(nextParameterIndex(), value)
}
fun expression(value : Int) : Unit {
statement.setInt(nextParameterIndex(), value)
}
fun expression(value : BigDecimal?) : Unit {
statement.setBigDecimal(nextParameterIndex(), value)
}
fun expression(value : Byte) : Unit {
statement.setByte(nextParameterIndex(), value)
}
fun expression(value : Double) : Unit {
statement.setDouble(nextParameterIndex(), value)
}
fun expression(value : Float) : Unit {
statement.setFloat(nextParameterIndex(), value)
}
fun expression(value : Long) : Unit {
statement.setLong(nextParameterIndex(), value)
}
fun expression(value : Short) : Unit {
statement.setShort(nextParameterIndex(), value)
}
fun expression(value : ByteArray) : Unit {
statement.setBytes(nextParameterIndex(), value)
}
fun expression(value : Date) : Unit {
statement.setDate(nextParameterIndex(), value)
}
fun expression(value : Time) : Unit {
statement.setTime(nextParameterIndex(), value)
}
fun expression(value : Timestamp) : Unit {
statement.setTimestamp(nextParameterIndex(), value)
}
// TODO bind other kinds!
/**
* Looks up the [[PreparedStatement]] in a cache or creates a new one
*/
protected fun lookupOrCreateStatement(): PreparedStatement {
val answer = connection.prepareStatement(sql)
if (answer == null) {
throw IllegalStateException("No PreparedStatement returned from $connection")
} else {
return answer
}
}
protected fun nextParameterIndex() : Int = ++parameterIndex
protected fun createSql() : String {
val out = StringBuilder()
var constantText = true
template.forEach {
out.append(if (constantText) it else "?")
constantText = !constantText
}
return out.toString() ?: ""
}
}
@@ -2,6 +2,7 @@ package kotlin.jdbc
import java.sql.*
import javax.sql.*
import kotlin.template.StringTemplate
/**
* Processes a connection from the pool using the given function block
@@ -38,4 +39,18 @@ fun DataSource.update(sql: String): Int {
*/
fun <T> DataSource.query(sql: String, block: (ResultSet) -> T): T {
return use{ it.query(sql, block) }
}
}
/**
* Performs the update using the given SQL using a [[StringTemplate]]
*/
fun DataSource.update(template : StringTemplate) : Int {
return use{ it.update(template) }
}
/**
* Perform a query on the connection using the SQL from the [[StringTemplate]] and processes the result set with a function
*/
fun <T> DataSource.query(template : StringTemplate, resultBlock : (ResultSet) -> T) : T {
return use{ it.query(template, resultBlock) }
}
@@ -10,175 +10,7 @@ import test.kotlin.jdbc. *
import junit.framework.TestCase
import javax.sql.DataSource
import java.sql.Connection
import java.sql.PreparedStatement
import java.sql.ResultSet
import java.math.BigDecimal
import java.sql.Date
import java.sql.Time
import java.sql.Timestamp
fun DataSource.update(template : StringTemplate) : Int {
return use{ it.update(template) }
}
fun <T> DataSource.query(template : StringTemplate, resultBlock : (ResultSet) -> T) : T {
return use{ it.query(template, resultBlock) }
}
fun Connection.update(template : StringTemplate) : Int {
val preparedStatement = prepare(template)
return preparedStatement.update()
}
fun <T> Connection.query(template : StringTemplate, resultBlock : (ResultSet) -> T) : T {
val preparedStatement = prepare(template)
return preparedStatement.query(resultBlock)
}
fun Connection.prepare(template : StringTemplate) : PreparedStatement {
val builder = PreparedStatementBuilder(template, this)
builder.bind()
return builder.statement
}
trait Binding {
fun bind(statement : PreparedStatement) : Unit
}
class PreparedStatementBuilder(val template : StringTemplate, val connection : Connection) {
private var parameterIndex = 0
public val sql : String = createSql()
public val statement: PreparedStatement = lookupOrCreateStatement()
/**
* Binds the values in the [[StringTemplate]] to the [[PreparedStatement]]
*/
fun bind() {
var constantText = true
template.forEach{
if (!constantText) {
expression(it)
}
constantText = !constantText
}
}
fun expression(value : Any?) : Unit {
// TODO causes compiler error
// if (value is Number) {
if (value is Int) {
expression(value)
} else if (value is Double) {
expression(value)
} else if (value is Float) {
expression(value)
} else if (value is BigDecimal) {
expression(value)
} else if (value is Byte) {
expression(value)
} else if (value is Long) {
expression(value)
} else if (value is Short) {
expression(value)
/*
} else {
expression(value.toDouble())
}
*/
}
else if (value is String) {
expression(value)
} else if (value is ByteArray) {
expression(value)
} else if (value is Date) {
expression(value)
} else if (value is Time) {
expression(value)
} else if (value is Timestamp) {
expression(value)
} else {
statement.setObject(nextParameterIndex(), value)
}
}
fun expression(value : String?) : Unit {
statement.setString(nextParameterIndex(), value)
}
fun expression(value : Int) : Unit {
statement.setInt(nextParameterIndex(), value)
}
fun expression(value : BigDecimal?) : Unit {
statement.setBigDecimal(nextParameterIndex(), value)
}
fun expression(value : Byte) : Unit {
statement.setByte(nextParameterIndex(), value)
}
fun expression(value : Double) : Unit {
statement.setDouble(nextParameterIndex(), value)
}
fun expression(value : Float) : Unit {
statement.setFloat(nextParameterIndex(), value)
}
fun expression(value : Long) : Unit {
statement.setLong(nextParameterIndex(), value)
}
fun expression(value : Short) : Unit {
statement.setShort(nextParameterIndex(), value)
}
fun expression(value : ByteArray) : Unit {
statement.setBytes(nextParameterIndex(), value)
}
fun expression(value : Date) : Unit {
statement.setDate(nextParameterIndex(), value)
}
fun expression(value : Time) : Unit {
statement.setTime(nextParameterIndex(), value)
}
fun expression(value : Timestamp) : Unit {
statement.setTimestamp(nextParameterIndex(), value)
}
// TODO bind other kinds!
/**
* Looks up the [[PreparedStatement]] in a cache or creates a new one
*/
protected fun lookupOrCreateStatement(): PreparedStatement {
val answer = connection.prepareStatement(sql)
if (answer == null) {
throw IllegalStateException("No PreparedStatement returned from $connection")
} else {
return answer
}
}
protected fun nextParameterIndex() : Int = ++parameterIndex
protected fun createSql() : String {
val out = StringBuilder()
var constantText = true
template.forEach {
out.append(if (constantText) it else "?")
constantText = !constantText
}
return out.toString() ?: ""
}
}
import java.sql. *
class JdbcTemplateTest : TestCase() {
@@ -32,6 +32,10 @@ class GenerateSiteTest : TestCase() {
config.title = "Kotlin API ($version)"
config.version = version
config.ignorePackages.add("org.jetbrains.kotlin")
config.ignorePackages.add("java")
config.ignorePackages.add("jet")
config.ignorePackages.add("junit")
config.ignorePackages.add("sun")
val compiler = KDocCompiler()
compiler.exec(System.out, args)