kotlin-jdbc can be found in its own repository: https://github.com/kotlin-projects/kotlin-jdbc
This commit is contained in:
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-project</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>kotlin-jdbc</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.3.164</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,224 +0,0 @@
|
||||
package kotlin.jdbc
|
||||
|
||||
import java.sql.*
|
||||
import kotlin.template.StringTemplate
|
||||
import java.math.BigDecimal
|
||||
import java.util.Properties
|
||||
|
||||
/**
|
||||
* create connection for the specified jdbc url with no credentials
|
||||
*/
|
||||
fun getConnection(url : String) : Connection = DriverManager.getConnection(url)
|
||||
|
||||
/**
|
||||
* 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 <T> Connection.use(block : (Connection) -> T) : T {
|
||||
try {
|
||||
return 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()
|
||||
if (statement != null) {
|
||||
return statement.use(block)
|
||||
} else {
|
||||
throw IllegalStateException("No Statement returned from $this")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an SQL update on the connection
|
||||
*/
|
||||
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
|
||||
*/
|
||||
fun <T> Connection.query(sql: String, block: (ResultSet) -> T): T {
|
||||
return statement{
|
||||
val rs = it.executeQuery(sql)
|
||||
block(rs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package kotlin.jdbc
|
||||
|
||||
import java.sql.*
|
||||
import javax.sql.*
|
||||
import kotlin.template.StringTemplate
|
||||
|
||||
/**
|
||||
* Processes a connection from the pool using the given function block
|
||||
*/
|
||||
fun <T> DataSource.use(block : (Connection) -> T): T {
|
||||
val connection = getConnection()
|
||||
if (connection != null) {
|
||||
try {
|
||||
return block(connection)
|
||||
} finally {
|
||||
connection.close()
|
||||
}
|
||||
} else {
|
||||
throw IllegalStateException("No Connection returned from $this")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to process a statement on this collection
|
||||
*/
|
||||
fun <T> DataSource.statement(block: (Statement) -> T): T {
|
||||
return use { it.statement(block) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an SQL update on the connection
|
||||
*/
|
||||
fun DataSource.update(sql: String): Int {
|
||||
return use { it.update(sql) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a query on the connection and processes the result set with a function
|
||||
*/
|
||||
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) }
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package kotlin.jdbc
|
||||
|
||||
/**
|
||||
* Helper method to process a statement on this collection
|
||||
*/
|
||||
import java.sql.PreparedStatement
|
||||
import java.sql.ResultSet
|
||||
|
||||
fun PreparedStatement.update(): Int {
|
||||
try {
|
||||
return this.executeUpdate()
|
||||
} finally {
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> PreparedStatement.query(block: (ResultSet) -> T): T {
|
||||
try {
|
||||
val resultSet = this.executeQuery()
|
||||
return block(resultSet)
|
||||
} finally {
|
||||
close()
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
package kotlin.jdbc
|
||||
|
||||
import java.sql.*
|
||||
|
||||
// Workaround for an import clash
|
||||
import kotlin.Array
|
||||
|
||||
/**
|
||||
* 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]]
|
||||
*/
|
||||
fun ResultSet.iterator() : Iterator<ResultSet> {
|
||||
val rs = this
|
||||
return object : Iterator<ResultSet>{
|
||||
public override fun hasNext() : Boolean = rs.next()
|
||||
|
||||
public override fun next() : ResultSet = rs
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns iterable that calls to the specified mapper function for each row
|
||||
*/
|
||||
fun <T> ResultSet.map(fn : (ResultSet) -> T) : Iterable<T> {
|
||||
val rs = this
|
||||
|
||||
val iterator = object : Iterator<T>{
|
||||
public override fun hasNext() : Boolean = rs.next()
|
||||
|
||||
public override fun next() : T = fn(rs)
|
||||
}
|
||||
|
||||
return object : Iterable<T> {
|
||||
public override fun iterator(): Iterator<T> = iterator
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array with column names
|
||||
*/
|
||||
fun ResultSet.getColumnNames() : Array<String> {
|
||||
val meta = getMetaData()
|
||||
return 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 : Array<String> = getColumnNames()) : Array<Any?> {
|
||||
return 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 : Array<String> = getColumnNames()) : 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)
|
||||
*/
|
||||
fun ResultSet.get(columnId: Int): Any? = this.getObject(columnId)
|
||||
|
||||
/**
|
||||
* Returns the value at the given column name
|
||||
*/
|
||||
fun ResultSet.get(columnName: String): Any? = this.getObject(columnName)
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package kotlin.jdbc
|
||||
|
||||
/**
|
||||
* Helper method to process a statement on this collection
|
||||
*/
|
||||
import java.sql.Statement
|
||||
|
||||
/**
|
||||
* Uses the statement with the given block then closes the statement
|
||||
*/
|
||||
fun <T, S : Statement> S.use(block : (S) -> T) : T {
|
||||
try {
|
||||
return block(this)
|
||||
} finally {
|
||||
close()
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
package kotlin.template
|
||||
|
||||
import kotlin.dom. *
|
||||
import org.w3c.dom.Node
|
||||
import java.util.Locale
|
||||
import java.text.NumberFormat
|
||||
import java.text.DateFormat
|
||||
import java.util.Date
|
||||
|
||||
@Deprecated("This class is part of an experimental implementation of string templates and is going to be removed")
|
||||
public class StringTemplate(private val values: Array<Any?>) {
|
||||
|
||||
/**
|
||||
* Converts the template into a String
|
||||
*/
|
||||
override fun toString(): String {
|
||||
val out = StringBuilder()
|
||||
forEach { out.append(it) }
|
||||
return out.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the given function on each value in the collection
|
||||
*/
|
||||
public fun forEach(fn: (Any?) -> Unit): Unit {
|
||||
for (v in values) {
|
||||
fn(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the string template into a string using the given formatter
|
||||
* to encode values as Strings performing any special encoding (such as for HTML)
|
||||
* or internationalisation.
|
||||
*
|
||||
* See [[HtmlFormatter] and [[LocaleFormatter] respectively.
|
||||
*/
|
||||
@Deprecated("This function is part of an experimental implementation of string templates and is going to be removed")
|
||||
public fun StringTemplate.toString(formatter: Formatter): String {
|
||||
val buffer = StringBuilder()
|
||||
append(buffer, formatter)
|
||||
return buffer.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the text representation of this string template to the given output
|
||||
* using the supplied formatter
|
||||
*/
|
||||
@Deprecated("This function is part of an experimental implementation of string templates and is going to be removed")
|
||||
public fun StringTemplate.append(out: Appendable, formatter: Formatter): Unit {
|
||||
var constantText = true
|
||||
this.forEach {
|
||||
if (constantText) {
|
||||
if (it == null) {
|
||||
throw IllegalStateException("No constant checks should be null");
|
||||
} else {
|
||||
val text = it.toString()
|
||||
out.append(text)
|
||||
}
|
||||
} else {
|
||||
formatter.format(out, it)
|
||||
}
|
||||
constantText = !constantText
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this string template to internationalised text using the supplied
|
||||
* [[LocaleFormatter]]
|
||||
*/
|
||||
@Deprecated("This function is part of an experimental implementation of string templates and is going to be removed")
|
||||
public fun StringTemplate.toLocale(formatter: LocaleFormatter = LocaleFormatter()): String = toString(formatter)
|
||||
|
||||
/**
|
||||
* Converts this string template to HTML text
|
||||
*/
|
||||
@Deprecated("This function is part of an experimental implementation of string templates and is going to be removed")
|
||||
public fun StringTemplate.toHtml(formatter: HtmlFormatter = HtmlFormatter()): String = toString(formatter)
|
||||
|
||||
/**
|
||||
* Represents a formatter and encoder of values in a [[StringTemplate]] which understands
|
||||
* how to format values for a particular [[Locale]] such as with the [[LocaleFormatter]] or
|
||||
* to escape particular characters in different output formats such as [[HtmlFormatter]
|
||||
*/
|
||||
@Deprecated("This interface is part of an experimental implementation of string templates and is going to be removed")
|
||||
public interface Formatter {
|
||||
public fun format(buffer: Appendable, value: Any?): Unit
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats strings with no special encoding other than allowing the null text to be
|
||||
* configured
|
||||
*/
|
||||
@Deprecated("This class is part of an experimental implementation of string templates and is going to be removed")
|
||||
public open class ToStringFormatter : Formatter {
|
||||
|
||||
private val nullString: String = "null"
|
||||
|
||||
override fun toString(): String = "ToStringFormatter"
|
||||
|
||||
public override fun format(out: Appendable, value: Any?) {
|
||||
if (value == null) {
|
||||
format(out, nullString)
|
||||
} else if (value is StringTemplate) {
|
||||
value.append(out, this)
|
||||
} else {
|
||||
format(out, value.toString())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given string allowing derived classes to override this method
|
||||
* to escape strings with special characters such as for HTML
|
||||
*/
|
||||
public open fun format(out: Appendable, text: String): Unit {
|
||||
out.append(text)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("This property is part of an experimental implementation of string templates and is going to be removed")
|
||||
public val defaultLocale: Locale = Locale.getDefault()
|
||||
|
||||
/**
|
||||
* Formats values using a given [[Locale]] for internationalisation
|
||||
*/
|
||||
@Deprecated("This class is part of an experimental implementation of string templates and is going to be removed")
|
||||
public open class LocaleFormatter(protected val locale: Locale = defaultLocale) : ToStringFormatter() {
|
||||
|
||||
override fun toString(): String = "LocaleFormatter{$locale}"
|
||||
|
||||
public var numberFormat: NumberFormat = NumberFormat.getInstance(locale)!!
|
||||
|
||||
public var dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, locale)!!
|
||||
|
||||
public override fun format(out: Appendable, value: Any?) {
|
||||
if (value is Number) {
|
||||
format(out, format(value))
|
||||
} else if (value is Date) {
|
||||
format(out, format(value))
|
||||
} else {
|
||||
super.format(out, value)
|
||||
}
|
||||
}
|
||||
|
||||
public fun format(number: Number): String {
|
||||
return numberFormat.format(number) ?: ""
|
||||
}
|
||||
|
||||
public fun format(date: Date): String {
|
||||
return dateFormat.format(date) ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats values for HTML encoding, escaping special characters in HTML.
|
||||
*/
|
||||
@Deprecated("This class is part of an experimental implementation of string templates and is going to be removed")
|
||||
public class HtmlFormatter(locale: Locale = defaultLocale) : LocaleFormatter(locale) {
|
||||
|
||||
override fun toString(): String = "HtmlFormatter{$locale}"
|
||||
|
||||
public override fun format(out: Appendable, value: Any?) {
|
||||
if (value is Node) {
|
||||
out.append(value.toXmlString())
|
||||
} else {
|
||||
super.format(out, value)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun format(buffer: Appendable, text: String): Unit {
|
||||
for (c in text) {
|
||||
if (c == '<') buffer.append("<")
|
||||
else if (c == '>') buffer.append(">")
|
||||
else if (c == '&') buffer.append("&")
|
||||
else if (c == '"') buffer.append(""")
|
||||
else buffer.append(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package test.kotlin.jdbc.experiment1
|
||||
|
||||
import kotlin.jdbc.*
|
||||
import kotlin.template.*
|
||||
import kotlin.test.*
|
||||
import org.junit.Test as test
|
||||
import test.kotlin.jdbc.*
|
||||
|
||||
class JdbcTemplateTest {
|
||||
//val dataSource = createDataSource()
|
||||
|
||||
@test fun templateInsert() {
|
||||
val id = 3
|
||||
val name = "Stepan"
|
||||
|
||||
// Mimicks the following code
|
||||
// dataSource.update("insert into foo (id, name) values ($id, $name)")
|
||||
|
||||
// TODO will use a tuple soon
|
||||
dataSource.update(
|
||||
StringTemplate(arrayOf("insert into foo (id, name) values (", id, ", ", name, ")"))
|
||||
)
|
||||
|
||||
// Mimicks
|
||||
// datasource.query("select * from foo where id = $id") { it.map{ it["name"] } }
|
||||
|
||||
val names = dataSource.query(
|
||||
StringTemplate(arrayOf("select * from foo where id = ", id))
|
||||
) {
|
||||
it.map{ it["name"] }.toList()
|
||||
}
|
||||
|
||||
println("Found names $names")
|
||||
val actual = names.first()
|
||||
assertEquals(name, actual)
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package test.kotlin.jdbc
|
||||
|
||||
import java.sql.ResultSet
|
||||
import javax.sql.DataSource
|
||||
import kotlin.jdbc.*
|
||||
import kotlin.test.*
|
||||
import org.h2.jdbcx.JdbcConnectionPool
|
||||
import org.junit.Test as test
|
||||
|
||||
public val dataSource : DataSource = createDataSource()
|
||||
|
||||
fun createDataSource() : DataSource {
|
||||
val dataSource = JdbcConnectionPool.create("jdbc:h2:mem:KotlinJdbcTest;DB_CLOSE_DELAY=-1", "user", "password")
|
||||
if (dataSource == null) {
|
||||
throw IllegalStateException("No DataSource created")
|
||||
} else {
|
||||
dataSource.update("create table foo (id int primary key, name varchar(100))")
|
||||
assertEquals(1, dataSource.update("insert into foo (id, name) values (1, 'James')"))
|
||||
assertEquals(1, dataSource.update("insert into foo (id, name) values (2, 'Andrey')"))
|
||||
|
||||
return dataSource
|
||||
}
|
||||
}
|
||||
|
||||
class JdbcTest {
|
||||
@test fun queryWithIndexColumnAccess() {
|
||||
dataSource.query("select * from foo") {
|
||||
for (row in it) {
|
||||
println("id ${row[1]} and name: ${row[2]}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@test fun queryWithNamedColumnAccess() {
|
||||
// query using names
|
||||
dataSource.query("select * from foo") {
|
||||
for (row in it) {
|
||||
println("name: ${row["name"]} has id ${row["id"]}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@test fun getValuesAsMap() {
|
||||
dataSource.query("select * from foo") {
|
||||
for (row in it) {
|
||||
println(row.getValuesAsMap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@test fun stringFormat() {
|
||||
dataSource.query(kotlin.template.StringTemplate(arrayOf("select * from foo where id = ", 1))) {
|
||||
for (row in it) {
|
||||
println(row.getValuesAsMap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@test fun mapIterator() {
|
||||
val mapper = { rs: ResultSet ->
|
||||
"id: ${rs["id"]}"
|
||||
}
|
||||
|
||||
dataSource.query("select * from foo") {
|
||||
for (row in it.map(mapper)) {
|
||||
println(row)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@test fun map() {
|
||||
dataSource.query("select * from foo") {
|
||||
val rows = it.map { "id: ${it["id"]}" }
|
||||
for (row in rows) {
|
||||
println(row)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@test fun count() {
|
||||
dataSource.query("select count(*) from foo") {
|
||||
println("count: ${it.singleInt()}")
|
||||
}
|
||||
}
|
||||
|
||||
@test fun formatCursor() {
|
||||
dataSource.query("select * from foo") {
|
||||
println(it.getColumnNames().toList().joinToString("\t"))
|
||||
|
||||
for (row in it) {
|
||||
println(it.getValues().joinToString("\t"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,6 @@
|
||||
<module>tools/kotlin-js-tests-junit</module>
|
||||
|
||||
<module>kunit</module>
|
||||
<module>kotlin-jdbc</module>
|
||||
|
||||
<module>examples/kotlin-java-example</module>
|
||||
<module>examples/js-example</module>
|
||||
|
||||
Reference in New Issue
Block a user