mirror of
https://github.com/corda/corda.git
synced 2025-04-26 05:49:44 +00:00
[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:
parent
1aa1189b36
commit
c009cbd91a
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 ?: "" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user