[CORDA-1468] Properly handle entites where NULLs can be inserted into DB (#3324)

* Allow proper null values on entities which fields can get NULL values.
This commit is contained in:
Maksymilian Pawlak 2018-06-11 13:12:19 +01:00 committed by GitHub
parent 1aa1189b36
commit c009cbd91a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 40 additions and 40 deletions

View File

@ -44,13 +44,13 @@ sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(bytes) {
* @throws IllegalArgumentException The input string does not contain 64 hexadecimal digits, or it contains incorrectly-encoded characters. * @throws IllegalArgumentException The input string does not contain 64 hexadecimal digits, or it contains incorrectly-encoded characters.
*/ */
@JvmStatic @JvmStatic
fun parse(str: String): SHA256 { fun parse(str: String?): SHA256 {
return str.toUpperCase().parseAsHex().let { return str?.toUpperCase()?.parseAsHex()?.let {
when (it.size) { when (it.size) {
32 -> SHA256(it) 32 -> SHA256(it)
else -> throw IllegalArgumentException("Provided string is ${it.size} bytes not 32 bytes in hex: $str") else -> throw IllegalArgumentException("Provided string is ${it.size} bytes not 32 bytes in hex: $str")
} }
} } ?: throw IllegalArgumentException("Provided string is null")
} }
/** /**

View File

@ -49,7 +49,7 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers
/** X500Name of participant parties **/ /** X500Name of participant parties **/
@Transient @Transient
open var participants: MutableSet<AbstractParty>? = null, open var participants: MutableSet<AbstractParty?>? = null,
/** [OwnableState] attributes */ /** [OwnableState] attributes */

View File

@ -25,7 +25,7 @@ object CashSchemaV1 : MappedSchema(schemaFamily = CashSchema.javaClass, version
class PersistentCashState( class PersistentCashState(
/** X500Name of owner party **/ /** X500Name of owner party **/
@Column(name = "owner_name", nullable = true) @Column(name = "owner_name", nullable = true)
var owner: AbstractParty, var owner: AbstractParty?,
@Column(name = "pennies", nullable = false) @Column(name = "pennies", nullable = false)
var pennies: Long, var pennies: Long,

View File

@ -17,7 +17,7 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve
/** product type */ /** product type */
@Column(name = "ccy_code", length = 3, nullable = false) @Column(name = "ccy_code", length = 3, nullable = false)
var currency: String, var currency: String,
participants: Set<AbstractParty>, participants: Set<AbstractParty?>,
owner: AbstractParty, owner: AbstractParty,
quantity: Long, quantity: Long,
issuerParty: AbstractParty, issuerParty: AbstractParty,
@ -27,6 +27,6 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve
@ElementCollection @ElementCollection
@Column(name = "participants", nullable = true) @Column(name = "participants", nullable = true)
@CollectionTable(name = "cash_states_v2_participants", joinColumns = [JoinColumn(name = "output_index", referencedColumnName = "output_index"), JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")]) @CollectionTable(name = "cash_states_v2_participants", joinColumns = [JoinColumn(name = "output_index", referencedColumnName = "output_index"), JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")])
override var participants: MutableSet<AbstractParty>? = null override var participants: MutableSet<AbstractParty?>? = null
} }
} }

View File

@ -23,11 +23,11 @@ object SampleCashSchemaV3 : MappedSchema(schemaFamily = CashSchema.javaClass, ve
/** X500Name of participant parties **/ /** X500Name of participant parties **/
@ElementCollection @ElementCollection
var participants: MutableSet<AbstractParty>? = null, var participants: MutableSet<AbstractParty?>? = null,
/** X500Name of owner party **/ /** X500Name of owner party **/
@Column(name = "owner_name", nullable = true) @Column(name = "owner_name", nullable = true)
var owner: AbstractParty, var owner: AbstractParty?,
@Column(name = "pennies", nullable = false) @Column(name = "pennies", nullable = false)
var pennies: Long, var pennies: Long,
@ -37,7 +37,7 @@ object SampleCashSchemaV3 : MappedSchema(schemaFamily = CashSchema.javaClass, ve
/** X500Name of issuer party **/ /** X500Name of issuer party **/
@Column(name = "issuer_name", nullable = true) @Column(name = "issuer_name", nullable = true)
var issuer: AbstractParty, var issuer: AbstractParty?,
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary") @Type(type = "corda-wrapper-binary")

View File

@ -42,6 +42,6 @@ object SampleCommercialPaperSchemaV2 : MappedSchema(schemaFamily = CommercialPap
@ElementCollection @ElementCollection
@Column(name = "participants") @Column(name = "participants")
@CollectionTable(name = "cp_states_v2_participants", joinColumns = [JoinColumn(name = "output_index", referencedColumnName = "output_index"), JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")]) @CollectionTable(name = "cp_states_v2_participants", joinColumns = [JoinColumn(name = "output_index", referencedColumnName = "output_index"), JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id")])
override var participants: MutableSet<AbstractParty>? = null override var participants: MutableSet<AbstractParty?>? = null
} }
} }

View File

@ -25,8 +25,8 @@ class PersistentScheduledFlowRepository(val database: CordaPersistence) : Schedu
} }
private fun fromPersistentEntity(scheduledStateRecord: NodeSchedulerService.PersistentScheduledState): Pair<StateRef, ScheduledStateRef> { private fun fromPersistentEntity(scheduledStateRecord: NodeSchedulerService.PersistentScheduledState): Pair<StateRef, ScheduledStateRef> {
val txId = scheduledStateRecord.output.txId ?: throw IllegalStateException("DB returned null SecureHash transactionId") val txId = scheduledStateRecord.output.txId
val index = scheduledStateRecord.output.index ?: throw IllegalStateException("DB returned null integer index") val index = scheduledStateRecord.output.index
return Pair(StateRef(SecureHash.parse(txId), index), ScheduledStateRef(StateRef(SecureHash.parse(txId), index), scheduledStateRecord.scheduledAt)) return Pair(StateRef(SecureHash.parse(txId), index), ScheduledStateRef(StateRef(SecureHash.parse(txId), index), scheduledStateRecord.scheduledAt))
} }

View File

@ -95,8 +95,8 @@ class PersistentIdentityService(override val trustRoot: X509Certificate,
@Column(name = "name", length = 128, nullable = false) @Column(name = "name", length = 128, nullable = false)
var name: String = "", var name: String = "",
@Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = false) @Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = true)
var publicKeyHash: String = "" var publicKeyHash: String? = ""
) : Serializable ) : Serializable
override val caCertStore: CertStore override val caCertStore: CertStore

View File

@ -33,8 +33,8 @@ class DBTransactionMappingStorage(private val database: CordaPersistence) : Stat
@Column(name = "tx_id", length = 64, nullable = false) @Column(name = "tx_id", length = 64, nullable = false)
var txId: String = "", var txId: String = "",
@Column(name = "state_machine_run_id", length = 36, nullable = false) @Column(name = "state_machine_run_id", length = 36, nullable = true)
var stateMachineRunId: String = "" var stateMachineRunId: String? = ""
) : Serializable ) : Serializable
private companion object { private companion object {

View File

@ -37,8 +37,8 @@ class PersistentUniquenessProvider(val clock: Clock) : UniquenessProvider, Singl
@EmbeddedId @EmbeddedId
val id: PersistentStateRef, val id: PersistentStateRef,
@Column(name = "consuming_transaction_id", nullable = false) @Column(name = "consuming_transaction_id", nullable = true)
val consumingTxHash: String val consumingTxHash: String?
) : Serializable ) : Serializable
@Entity @Entity
@ -50,11 +50,11 @@ class PersistentUniquenessProvider(val clock: Clock) : UniquenessProvider, Singl
@Column(nullable = true) @Column(nullable = true)
val id: Int? = null, val id: Int? = null,
@Column(name = "consuming_transaction_id", nullable = false) @Column(name = "consuming_transaction_id", nullable = true)
val consumingTxHash: String, val consumingTxHash: String?,
@Column(name = "requesting_party_name", nullable = false) @Column(name = "requesting_party_name", nullable = true)
var partyName: String, var partyName: String?,
@Lob @Lob
@Column(name = "request_signature", nullable = false) @Column(name = "request_signature", nullable = false)

View File

@ -90,8 +90,8 @@ class RaftUniquenessProvider(
class CommittedState( class CommittedState(
@EmbeddedId @EmbeddedId
val id: PersistentStateRef, val id: PersistentStateRef,
@Column(name = "consuming_transaction_id", nullable = false) @Column(name = "consuming_transaction_id", nullable = true)
var value: String = "", var value: String? = "",
@Column(name = "raft_log_index", nullable = false) @Column(name = "raft_log_index", nullable = false)
var index: Long = 0 var index: Long = 0
) : Serializable ) : Serializable

View File

@ -22,15 +22,15 @@ class ContractUpgradeServiceImpl : ContractUpgradeService, SingletonSerializeAsT
var stateRef: String = "", var stateRef: String = "",
/** refers to the UpgradedContract class name*/ /** refers to the UpgradedContract class name*/
@Column(name = "contract_class_name", nullable = false) @Column(name = "contract_class_name", nullable = true)
var upgradedContractClassName: String = "" var upgradedContractClassName: String? = ""
) : Serializable ) : Serializable
private companion object { private companion object {
fun createContractUpgradesMap(): PersistentMap<String, String, DBContractUpgrade, String> { fun createContractUpgradesMap(): PersistentMap<String, String, DBContractUpgrade, String> {
return PersistentMap( return PersistentMap(
toPersistentEntityKey = { it }, toPersistentEntityKey = { it },
fromPersistentEntity = { Pair(it.stateRef, it.upgradedContractClassName) }, fromPersistentEntity = { Pair(it.stateRef, it.upgradedContractClassName ?: "") },
toPersistentEntity = { key: String, value: String -> toPersistentEntity = { key: String, value: String ->
DBContractUpgrade().apply { DBContractUpgrade().apply {
stateRef = key stateRef = key

View File

@ -242,7 +242,7 @@ class NodeVaultService(
val txIdPredicate = criteriaBuilder.equal(vaultStates.get<Vault.StateStatus>(VaultSchemaV1.VaultTxnNote::txId.name), txnId.toString()) val txIdPredicate = criteriaBuilder.equal(vaultStates.get<Vault.StateStatus>(VaultSchemaV1.VaultTxnNote::txId.name), txnId.toString())
criteriaQuery.where(txIdPredicate) criteriaQuery.where(txIdPredicate)
val results = session.createQuery(criteriaQuery).resultList val results = session.createQuery(criteriaQuery).resultList
results.asIterable().map { it.note } results.asIterable().map { it.note ?: "" }
} }
} }

View File

@ -74,7 +74,7 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
joinColumns = [(JoinColumn(name = "output_index", referencedColumnName = "output_index")), (JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))], joinColumns = [(JoinColumn(name = "output_index", referencedColumnName = "output_index")), (JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))],
foreignKey = ForeignKey(name = "FK__lin_stat_parts__lin_stat")) foreignKey = ForeignKey(name = "FK__lin_stat_parts__lin_stat"))
@Column(name = "participants") @Column(name = "participants")
var participants: MutableSet<AbstractParty>? = null, var participants: MutableSet<AbstractParty?>? = null,
// Reason for not using Set is described here: // Reason for not using Set is described here:
// https://stackoverflow.com/questions/44213074/kotlin-collection-has-neither-generic-type-or-onetomany-targetentity // https://stackoverflow.com/questions/44213074/kotlin-collection-has-neither-generic-type-or-onetomany-targetentity
@ -111,7 +111,7 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
/** X500Name of owner party **/ /** X500Name of owner party **/
@Column(name = "owner_name", nullable = true) @Column(name = "owner_name", nullable = true)
var owner: AbstractParty, var owner: AbstractParty?,
/** [FungibleAsset] attributes /** [FungibleAsset] attributes
* *
@ -127,7 +127,7 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
/** X500Name of issuer party **/ /** X500Name of issuer party **/
@Column(name = "issuer_name", nullable = true) @Column(name = "issuer_name", nullable = true)
var issuer: AbstractParty, var issuer: AbstractParty?,
@Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false)
@Type(type = "corda-wrapper-binary") @Type(type = "corda-wrapper-binary")
@ -149,11 +149,11 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio
@Column(name = "seq_no", nullable = false) @Column(name = "seq_no", nullable = false)
var seqNo: Int, var seqNo: Int,
@Column(name = "transaction_id", length = 64, nullable = false) @Column(name = "transaction_id", length = 64, nullable = true)
var txId: String, var txId: String?,
@Column(name = "note", nullable = false) @Column(name = "note", nullable = true)
var note: String var note: String?
) : Serializable { ) : Serializable {
constructor(txId: String, note: String) : this(0, txId, note) constructor(txId: String, note: String) : this(0, txId, note)
} }

View File

@ -17,7 +17,7 @@ class PersistentMapTests {
private fun createTestMap(): PersistentMap<String, String, ContractUpgradeServiceImpl.DBContractUpgrade, String> { private fun createTestMap(): PersistentMap<String, String, ContractUpgradeServiceImpl.DBContractUpgrade, String> {
return PersistentMap( return PersistentMap(
toPersistentEntityKey = { it }, toPersistentEntityKey = { it },
fromPersistentEntity = { Pair(it.stateRef, it.upgradedContractClassName) }, fromPersistentEntity = { Pair(it.stateRef, it.upgradedContractClassName ?: "") },
toPersistentEntity = { key: String, value: String -> toPersistentEntity = { key: String, value: String ->
ContractUpgradeServiceImpl.DBContractUpgrade().apply { ContractUpgradeServiceImpl.DBContractUpgrade().apply {
stateRef = key stateRef = key

View File

@ -41,8 +41,8 @@ object DummyLinearStateSchemaV1 : MappedSchema(schemaFamily = DummyLinearStateSc
/** /**
* Dummy attributes * Dummy attributes
*/ */
@Column(name = "linear_string", nullable = false) @Column(name = "linear_string", nullable = true)
var linearString: String, var linearString: String?,
@Column(name = "linear_number", nullable = false) @Column(name = "linear_number", nullable = false)
var linearNumber: Long, var linearNumber: Long,

View File

@ -21,7 +21,7 @@ object DummyLinearStateSchemaV2 : MappedSchema(schemaFamily = DummyLinearStateSc
@CollectionTable(name = "dummy_linear_states_v2_parts", joinColumns = [(JoinColumn(name = "output_index", referencedColumnName = "output_index")), (JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))]) @CollectionTable(name = "dummy_linear_states_v2_parts", joinColumns = [(JoinColumn(name = "output_index", referencedColumnName = "output_index")), (JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))])
override var participants: MutableSet<AbstractParty>? = null, override var participants: MutableSet<AbstractParty>? = null,
@Column(name = "linear_string", nullable = false) var linearString: String, @Column(name = "linear_string", nullable = true) var linearString: String?,
@Column(name = "linear_number", nullable = false) var linearNumber: Long, @Column(name = "linear_number", nullable = false) var linearNumber: Long,