Fix SQL statement used by CashSelection on SQL Server (#641)

This commit is contained in:
igor nitto 2018-03-28 18:13:29 +01:00 committed by GitHub
parent 848c516422
commit d1f6f0a5bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -11,6 +11,7 @@
package net.corda.finance.contracts.asset.cash.selection package net.corda.finance.contracts.asset.cash.selection
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.crypto.toStringShort
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.OpaqueBytes
@ -38,7 +39,8 @@ class CashSelectionSQLServerImpl : AbstractCashSelection(maxRetries = 16, retryS
override fun toString() = "${this::class.java} for $JDBC_DRIVER_NAME" override fun toString() = "${this::class.java} for $JDBC_DRIVER_NAME"
override fun executeQuery(connection: Connection, amount: Amount<Currency>, lockId: UUID, notary: Party?, override fun executeQuery(connection: Connection, amount: Amount<Currency>, lockId: UUID, notary: Party?,
onlyFromIssuerParties: Set<AbstractParty>, withIssuerRefs: Set<OpaqueBytes>, withResultSet: (ResultSet) -> Boolean): Boolean { onlyFromIssuerParties: Set<AbstractParty>,
withIssuerRefs: Set<OpaqueBytes>, withResultSet: (ResultSet) -> Boolean): Boolean {
val selectJoin = """ val selectJoin = """
WITH row(transaction_id, output_index, pennies, total, lock_id) AS WITH row(transaction_id, output_index, pennies, total, lock_id) AS
@ -52,10 +54,20 @@ class CashSelectionSQLServerImpl : AbstractCashSelection(maxRetries = 16, retryS
AND (vs.lock_id = ? OR vs.lock_id is null)"""+ AND (vs.lock_id = ? OR vs.lock_id is null)"""+
(if (notary != null) (if (notary != null)
" AND vs.notary_name = ?" else "") + " AND vs.notary_name = ?" else "") +
(if (onlyFromIssuerParties.isNotEmpty()) // mssql-server driver does not implement setArray(), so in the following way
" AND ccs.issuer_key_hash IN (?)" else "") + // we explicitly unpack the parameters list
(if (withIssuerRefs.isNotEmpty()) (if (onlyFromIssuerParties.isNotEmpty()) {
" AND ccs.issuer_ref IN (?)" else "") + val repeats = generateSequence { "?" }
.take(onlyFromIssuerParties.size)
.joinToString (",")
" AND ccs.issuer_key_hash IN ($repeats)"
} else { "" }) +
(if (withIssuerRefs.isNotEmpty()) {
val repeats = generateSequence { "?" }
.take(withIssuerRefs.size)
.joinToString (",")
" AND ccs.issuer_ref IN ($repeats)"
} else { "" }) +
""") """)
SELECT row.transaction_id, row.output_index, row.pennies, row.total, row.lock_id SELECT row.transaction_id, row.output_index, row.pennies, row.total, row.lock_id
FROM row where row.total <= ? + row.pennies""" FROM row where row.total <= ? + row.pennies"""
@ -67,10 +79,12 @@ class CashSelectionSQLServerImpl : AbstractCashSelection(maxRetries = 16, retryS
statement.setString(++pIndex, lockId.toString()) statement.setString(++pIndex, lockId.toString())
if (notary != null) if (notary != null)
statement.setString(++pIndex, notary.name.toString()) statement.setString(++pIndex, notary.name.toString())
if (onlyFromIssuerParties.isNotEmpty()) onlyFromIssuerParties.map { it.owningKey.toStringShort() }.forEach {
statement.setObject(++pIndex, onlyFromIssuerParties.map { it.owningKey.toBase58String() as Any }.toTypedArray()) statement.setObject(++pIndex, it)
if (withIssuerRefs.isNotEmpty()) }
statement.setObject(++pIndex, withIssuerRefs.map { it.bytes as Any }.toTypedArray()) withIssuerRefs.map { it.bytes }.forEach {
statement.setBytes(++pIndex, it)
}
statement.setLong(++pIndex, amount.quantity) statement.setLong(++pIndex, amount.quantity)
log.debug(selectJoin) log.debug(selectJoin)