Additional methods to extract data from ResultSet and to create new connection with no DataSource
This commit is contained in:
@@ -3,9 +3,47 @@ package kotlin.jdbc
|
|||||||
import java.sql.*
|
import java.sql.*
|
||||||
import kotlin.template.StringTemplate
|
import kotlin.template.StringTemplate
|
||||||
import java.math.BigDecimal
|
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 {
|
fun <T> Connection.statement(block: (Statement) -> T): T {
|
||||||
val statement = createStatement()
|
val statement = createStatement()
|
||||||
|
|||||||
@@ -4,6 +4,18 @@ import java.sql.*
|
|||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.Collection
|
import java.util.Collection
|
||||||
import java.util.List
|
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]]
|
* 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)
|
* 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
|
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 org.h2.jdbcx.JdbcDataSource
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
import org.h2.jdbcx.JdbcConnectionPool
|
import org.h2.jdbcx.JdbcConnectionPool
|
||||||
|
import kotlin.nullable.forEach
|
||||||
|
import java.sql.ResultSet
|
||||||
|
|
||||||
public val dataSource : DataSource = createDataSource()
|
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