Merge pull request #116 from cy6erGn0m/3cf1fd5377f4cf6c719c93f513bbd2b96a1213b3
kotlin-jdbc: Additional extenstions to work with ResultSet
This commit is contained in:
@@ -3,9 +3,47 @@ package kotlin.jdbc
|
||||
import java.sql.*
|
||||
import kotlin.template.StringTemplate
|
||||
import java.math.BigDecimal
|
||||
import java.util.Map
|
||||
import java.util.Properties
|
||||
|
||||
private fun Map<String, String>.toProperties() : Properties {
|
||||
val p = Properties()
|
||||
|
||||
this.keySet().forEach {
|
||||
p.put(it, this[it])
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to process a statement on this collection
|
||||
* create connection for the specified jdbc url with no credentials
|
||||
*/
|
||||
fun getConnection(url : String) : Connection = DriverManager.getConnection(url).sure()
|
||||
|
||||
/**
|
||||
* create connection for the specified jdbc url and properties
|
||||
*/
|
||||
fun getConnection(url : String, info : Map<String, String>) : Connection = DriverManager.getConnection(url, info.toProperties())!!
|
||||
|
||||
/**
|
||||
* create connection for the specified jdbc url and credentials
|
||||
*/
|
||||
fun getConnection(url : String, user : String, password : String) : Connection = DriverManager.getConnection(url, user, password)!!
|
||||
|
||||
/**
|
||||
* Executes specified block with connection and close connection after this
|
||||
*/
|
||||
fun Connection.use(block : (Connection) -> Any?) : Unit {
|
||||
try {
|
||||
block(this)
|
||||
} finally {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to process a statement on this connection
|
||||
*/
|
||||
fun <T> Connection.statement(block: (Statement) -> T): T {
|
||||
val statement = createStatement()
|
||||
|
||||
@@ -4,6 +4,18 @@ import java.sql.*
|
||||
import java.util.ArrayList
|
||||
import java.util.Collection
|
||||
import java.util.List
|
||||
import java.util.Map
|
||||
|
||||
/**
|
||||
* Executes the specfied block with result set and then closes it
|
||||
*/
|
||||
public fun <R> ResultSet.use(block : (ResultSet) -> R) : R {
|
||||
try {
|
||||
return block(this)
|
||||
} finally {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an iterator through a [[ResultSet]]
|
||||
@@ -18,6 +30,56 @@ fun ResultSet.iterator() : Iterator<ResultSet> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns iterable that calls to the specified mapper function for each row
|
||||
*/
|
||||
fun <T> ResultSet.getMapped(fn : (ResultSet) -> T) : jet.Iterable<T> {
|
||||
val rs = this
|
||||
|
||||
val iterator = object : Iterator<T>{
|
||||
public override val hasNext : Boolean
|
||||
get() = rs.next()
|
||||
|
||||
public override fun next() : T = fn(rs)
|
||||
}
|
||||
|
||||
return object : jet.Iterable<T> {
|
||||
public override fun iterator(): Iterator<T> = iterator
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array with column names
|
||||
*/
|
||||
fun ResultSet.getColumnNames() : jet.Array<String> {
|
||||
val meta = getMetaData().sure()
|
||||
return jet.Array<String>(meta.getColumnCount(), {meta.getColumnName(it + 1) ?: it.toString()})
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array filled with values from current row in the cursor. Values will have the same order as column's order
|
||||
* @columnNames you can specify column names to extract otherwise all columns will be extracted
|
||||
*/
|
||||
fun ResultSet.getValues(columnNames : jet.Array<String> = getColumnNames()) : jet.Array<Any?> {
|
||||
return jet.Array<Any?>(columnNames.size, {
|
||||
this[columnNames[it]]
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Return map filled with values from current row in the cursor. Uses column names as keys for result map.
|
||||
* @param columnNames you can specify column names to extract otherwise all columns will be extracted
|
||||
*/
|
||||
fun ResultSet.getValuesAsMap(columnNames : jet.Array<String> = getColumnNames()) : java.util.Map<String, Any?> {
|
||||
val result = java.util.HashMap<String, Any?>(columnNames.size)
|
||||
|
||||
columnNames.forEach {
|
||||
result[it] = this[it]
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the given column index (starting at 1)
|
||||
*/
|
||||
@@ -47,3 +109,26 @@ fun <T> ResultSet.mapTo(result: Collection<T>, fn: (ResultSet) -> T) : Collectio
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun ResultSet.ensureHasRow() : ResultSet {
|
||||
if (!next()) {
|
||||
throw IllegalStateException("There are no rows left in cursor")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns int value from the cursor at first column. May be useful to get result of count(*)
|
||||
*/
|
||||
fun ResultSet.singleInt() : Int = ensureHasRow().getInt(1)
|
||||
|
||||
/**
|
||||
* Returns long value from the cursor at first column.
|
||||
*/
|
||||
fun ResultSet.singleLong() : Long = ensureHasRow().getLong(1)
|
||||
|
||||
/**
|
||||
* Returns double value from the cursor at first column.
|
||||
*/
|
||||
fun ResultSet.singleDouble() : Double = ensureHasRow().getDouble(1)
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import junit.framework.TestCase
|
||||
import org.h2.jdbcx.JdbcDataSource
|
||||
import javax.sql.DataSource
|
||||
import org.h2.jdbcx.JdbcConnectionPool
|
||||
import kotlin.nullable.forEach
|
||||
import java.sql.ResultSet
|
||||
|
||||
public val dataSource : DataSource = createDataSource()
|
||||
|
||||
@@ -40,4 +42,48 @@ class JdbcTest : TestCase() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testGetValuesAsMap() {
|
||||
dataSource.query("select * from foo") {
|
||||
for (row in it) {
|
||||
println(row.getValuesAsMap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testStringFormat() {
|
||||
dataSource.query(kotlin.template.StringTemplate(array("select * from foo where id = ", 1))) {
|
||||
for (row in it) {
|
||||
println(row.getValuesAsMap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testMapIterator() {
|
||||
val mapper = { (rs : ResultSet) ->
|
||||
"id: ${rs["id"]}"
|
||||
}
|
||||
|
||||
dataSource.query("select * from foo") {
|
||||
for (row in it.getMapped(mapper)) {
|
||||
println(row)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testCount() {
|
||||
dataSource.query("select count(*) from foo") {
|
||||
println("count: ${it.singleInt()}")
|
||||
}
|
||||
}
|
||||
|
||||
fun testFormatCursor() {
|
||||
dataSource.query("select * from foo") {
|
||||
println(it.getColumnNames().toList().makeString("\t"))
|
||||
|
||||
for (row in it) {
|
||||
println(it.getValues().makeString("\t"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user