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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user