From c009cbd91ab8b67a3bede853883b932cc3ebf444 Mon Sep 17 00:00:00 2001 From: Maksymilian Pawlak Date: Mon, 11 Jun 2018 13:12:19 +0100 Subject: [PATCH] [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. --- .../kotlin/net/corda/core/crypto/SecureHash.kt | 6 +++--- .../kotlin/net/corda/core/schemas/CommonSchema.kt | 2 +- .../net/corda/finance/schemas/CashSchemaV1.kt | 2 +- .../corda/finance/schemas/SampleCashSchemaV2.kt | 4 ++-- .../corda/finance/schemas/SampleCashSchemaV3.kt | 6 +++--- .../schemas/SampleCommercialPaperSchemaV2.kt | 2 +- .../events/PersistentScheduledFlowRepository.kt | 4 ++-- .../services/identity/PersistentIdentityService.kt | 4 ++-- .../persistence/DBTransactionMappingStorage.kt | 4 ++-- .../transactions/PersistentUniquenessProvider.kt | 12 ++++++------ .../transactions/RaftUniquenessProvider.kt | 4 ++-- .../services/upgrade/ContractUpgradeServiceImpl.kt | 6 +++--- .../corda/node/services/vault/NodeVaultService.kt | 2 +- .../net/corda/node/services/vault/VaultSchema.kt | 14 +++++++------- .../net/corda/node/utilities/PersistentMapTests.kt | 2 +- .../internal/vault/DummyLinearStateSchemaV1.kt | 4 ++-- .../internal/vault/DummyLinearStateSchemaV2.kt | 2 +- 17 files changed, 40 insertions(+), 40 deletions(-) diff --git a/core/src/main/kotlin/net/corda/core/crypto/SecureHash.kt b/core/src/main/kotlin/net/corda/core/crypto/SecureHash.kt index cc0d35131a..78ccc8b3ca 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/SecureHash.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/SecureHash.kt @@ -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. */ @JvmStatic - fun parse(str: String): SHA256 { - return str.toUpperCase().parseAsHex().let { + fun parse(str: String?): SHA256 { + return str?.toUpperCase()?.parseAsHex()?.let { when (it.size) { 32 -> SHA256(it) else -> throw IllegalArgumentException("Provided string is ${it.size} bytes not 32 bytes in hex: $str") } - } + } ?: throw IllegalArgumentException("Provided string is null") } /** diff --git a/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt b/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt index be1928ad87..035f248e10 100644 --- a/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt +++ b/core/src/main/kotlin/net/corda/core/schemas/CommonSchema.kt @@ -49,7 +49,7 @@ object CommonSchemaV1 : MappedSchema(schemaFamily = CommonSchema.javaClass, vers /** X500Name of participant parties **/ @Transient - open var participants: MutableSet? = null, + open var participants: MutableSet? = null, /** [OwnableState] attributes */ diff --git a/finance/src/main/kotlin/net/corda/finance/schemas/CashSchemaV1.kt b/finance/src/main/kotlin/net/corda/finance/schemas/CashSchemaV1.kt index 8ae6d96cd6..3dfa84d354 100644 --- a/finance/src/main/kotlin/net/corda/finance/schemas/CashSchemaV1.kt +++ b/finance/src/main/kotlin/net/corda/finance/schemas/CashSchemaV1.kt @@ -25,7 +25,7 @@ object CashSchemaV1 : MappedSchema(schemaFamily = CashSchema.javaClass, version class PersistentCashState( /** X500Name of owner party **/ @Column(name = "owner_name", nullable = true) - var owner: AbstractParty, + var owner: AbstractParty?, @Column(name = "pennies", nullable = false) var pennies: Long, diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt index dacef2cfa8..a17f863841 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV2.kt @@ -17,7 +17,7 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve /** product type */ @Column(name = "ccy_code", length = 3, nullable = false) var currency: String, - participants: Set, + participants: Set, owner: AbstractParty, quantity: Long, issuerParty: AbstractParty, @@ -27,6 +27,6 @@ object SampleCashSchemaV2 : MappedSchema(schemaFamily = CashSchema.javaClass, ve @ElementCollection @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")]) - override var participants: MutableSet? = null + override var participants: MutableSet? = null } } diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV3.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV3.kt index 85a6c63de2..987210cd84 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV3.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCashSchemaV3.kt @@ -23,11 +23,11 @@ object SampleCashSchemaV3 : MappedSchema(schemaFamily = CashSchema.javaClass, ve /** X500Name of participant parties **/ @ElementCollection - var participants: MutableSet? = null, + var participants: MutableSet? = null, /** X500Name of owner party **/ @Column(name = "owner_name", nullable = true) - var owner: AbstractParty, + var owner: AbstractParty?, @Column(name = "pennies", nullable = false) var pennies: Long, @@ -37,7 +37,7 @@ object SampleCashSchemaV3 : MappedSchema(schemaFamily = CashSchema.javaClass, ve /** X500Name of issuer party **/ @Column(name = "issuer_name", nullable = true) - var issuer: AbstractParty, + var issuer: AbstractParty?, @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") diff --git a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt index ab862ce600..9eeac47cc0 100644 --- a/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt +++ b/finance/src/test/kotlin/net/corda/finance/schemas/SampleCommercialPaperSchemaV2.kt @@ -42,6 +42,6 @@ object SampleCommercialPaperSchemaV2 : MappedSchema(schemaFamily = CommercialPap @ElementCollection @Column(name = "participants") @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? = null + override var participants: MutableSet? = null } } diff --git a/node/src/main/kotlin/net/corda/node/services/events/PersistentScheduledFlowRepository.kt b/node/src/main/kotlin/net/corda/node/services/events/PersistentScheduledFlowRepository.kt index 10624f9c96..cff3ac39cb 100644 --- a/node/src/main/kotlin/net/corda/node/services/events/PersistentScheduledFlowRepository.kt +++ b/node/src/main/kotlin/net/corda/node/services/events/PersistentScheduledFlowRepository.kt @@ -25,8 +25,8 @@ class PersistentScheduledFlowRepository(val database: CordaPersistence) : Schedu } private fun fromPersistentEntity(scheduledStateRecord: NodeSchedulerService.PersistentScheduledState): Pair { - val txId = scheduledStateRecord.output.txId ?: throw IllegalStateException("DB returned null SecureHash transactionId") - val index = scheduledStateRecord.output.index ?: throw IllegalStateException("DB returned null integer index") + val txId = scheduledStateRecord.output.txId + val index = scheduledStateRecord.output.index return Pair(StateRef(SecureHash.parse(txId), index), ScheduledStateRef(StateRef(SecureHash.parse(txId), index), scheduledStateRecord.scheduledAt)) } diff --git a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt index ae314bdc16..9f080c4b42 100644 --- a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt +++ b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt @@ -95,8 +95,8 @@ class PersistentIdentityService(override val trustRoot: X509Certificate, @Column(name = "name", length = 128, nullable = false) var name: String = "", - @Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = false) - var publicKeyHash: String = "" + @Column(name = "pk_hash", length = MAX_HASH_HEX_SIZE, nullable = true) + var publicKeyHash: String? = "" ) : Serializable override val caCertStore: CertStore diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt index 2f00c93920..467e711c98 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt @@ -33,8 +33,8 @@ class DBTransactionMappingStorage(private val database: CordaPersistence) : Stat @Column(name = "tx_id", length = 64, nullable = false) var txId: String = "", - @Column(name = "state_machine_run_id", length = 36, nullable = false) - var stateMachineRunId: String = "" + @Column(name = "state_machine_run_id", length = 36, nullable = true) + var stateMachineRunId: String? = "" ) : Serializable private companion object { diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/PersistentUniquenessProvider.kt b/node/src/main/kotlin/net/corda/node/services/transactions/PersistentUniquenessProvider.kt index d6ede5cd4a..77d17a1faf 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/PersistentUniquenessProvider.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/PersistentUniquenessProvider.kt @@ -37,8 +37,8 @@ class PersistentUniquenessProvider(val clock: Clock) : UniquenessProvider, Singl @EmbeddedId val id: PersistentStateRef, - @Column(name = "consuming_transaction_id", nullable = false) - val consumingTxHash: String + @Column(name = "consuming_transaction_id", nullable = true) + val consumingTxHash: String? ) : Serializable @Entity @@ -50,11 +50,11 @@ class PersistentUniquenessProvider(val clock: Clock) : UniquenessProvider, Singl @Column(nullable = true) val id: Int? = null, - @Column(name = "consuming_transaction_id", nullable = false) - val consumingTxHash: String, + @Column(name = "consuming_transaction_id", nullable = true) + val consumingTxHash: String?, - @Column(name = "requesting_party_name", nullable = false) - var partyName: String, + @Column(name = "requesting_party_name", nullable = true) + var partyName: String?, @Lob @Column(name = "request_signature", nullable = false) diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt b/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt index 1d8d12acf4..ea339c8140 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt @@ -90,8 +90,8 @@ class RaftUniquenessProvider( class CommittedState( @EmbeddedId val id: PersistentStateRef, - @Column(name = "consuming_transaction_id", nullable = false) - var value: String = "", + @Column(name = "consuming_transaction_id", nullable = true) + var value: String? = "", @Column(name = "raft_log_index", nullable = false) var index: Long = 0 ) : Serializable diff --git a/node/src/main/kotlin/net/corda/node/services/upgrade/ContractUpgradeServiceImpl.kt b/node/src/main/kotlin/net/corda/node/services/upgrade/ContractUpgradeServiceImpl.kt index 54014442a3..909d98f11c 100644 --- a/node/src/main/kotlin/net/corda/node/services/upgrade/ContractUpgradeServiceImpl.kt +++ b/node/src/main/kotlin/net/corda/node/services/upgrade/ContractUpgradeServiceImpl.kt @@ -22,15 +22,15 @@ class ContractUpgradeServiceImpl : ContractUpgradeService, SingletonSerializeAsT var stateRef: String = "", /** refers to the UpgradedContract class name*/ - @Column(name = "contract_class_name", nullable = false) - var upgradedContractClassName: String = "" + @Column(name = "contract_class_name", nullable = true) + var upgradedContractClassName: String? = "" ) : Serializable private companion object { fun createContractUpgradesMap(): PersistentMap { return PersistentMap( toPersistentEntityKey = { it }, - fromPersistentEntity = { Pair(it.stateRef, it.upgradedContractClassName) }, + fromPersistentEntity = { Pair(it.stateRef, it.upgradedContractClassName ?: "") }, toPersistentEntity = { key: String, value: String -> DBContractUpgrade().apply { stateRef = key diff --git a/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt b/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt index e13224e05e..06ffc886b2 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt @@ -242,7 +242,7 @@ class NodeVaultService( val txIdPredicate = criteriaBuilder.equal(vaultStates.get(VaultSchemaV1.VaultTxnNote::txId.name), txnId.toString()) criteriaQuery.where(txIdPredicate) val results = session.createQuery(criteriaQuery).resultList - results.asIterable().map { it.note } + results.asIterable().map { it.note ?: "" } } } diff --git a/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt b/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt index 081fdc1060..4d0bacaa95 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/VaultSchema.kt @@ -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"))], foreignKey = ForeignKey(name = "FK__lin_stat_parts__lin_stat")) @Column(name = "participants") - var participants: MutableSet? = null, + var participants: MutableSet? = null, // Reason for not using Set is described here: // 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 **/ @Column(name = "owner_name", nullable = true) - var owner: AbstractParty, + var owner: AbstractParty?, /** [FungibleAsset] attributes * @@ -127,7 +127,7 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio /** X500Name of issuer party **/ @Column(name = "issuer_name", nullable = true) - var issuer: AbstractParty, + var issuer: AbstractParty?, @Column(name = "issuer_ref", length = MAX_ISSUER_REF_SIZE, nullable = false) @Type(type = "corda-wrapper-binary") @@ -149,11 +149,11 @@ object VaultSchemaV1 : MappedSchema(schemaFamily = VaultSchema.javaClass, versio @Column(name = "seq_no", nullable = false) var seqNo: Int, - @Column(name = "transaction_id", length = 64, nullable = false) - var txId: String, + @Column(name = "transaction_id", length = 64, nullable = true) + var txId: String?, - @Column(name = "note", nullable = false) - var note: String + @Column(name = "note", nullable = true) + var note: String? ) : Serializable { constructor(txId: String, note: String) : this(0, txId, note) } diff --git a/node/src/test/kotlin/net/corda/node/utilities/PersistentMapTests.kt b/node/src/test/kotlin/net/corda/node/utilities/PersistentMapTests.kt index 671e9c1fc8..2ee96bae91 100644 --- a/node/src/test/kotlin/net/corda/node/utilities/PersistentMapTests.kt +++ b/node/src/test/kotlin/net/corda/node/utilities/PersistentMapTests.kt @@ -17,7 +17,7 @@ class PersistentMapTests { private fun createTestMap(): PersistentMap { return PersistentMap( toPersistentEntityKey = { it }, - fromPersistentEntity = { Pair(it.stateRef, it.upgradedContractClassName) }, + fromPersistentEntity = { Pair(it.stateRef, it.upgradedContractClassName ?: "") }, toPersistentEntity = { key: String, value: String -> ContractUpgradeServiceImpl.DBContractUpgrade().apply { stateRef = key diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt index c662cb9ae6..a04d3b06bb 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV1.kt @@ -41,8 +41,8 @@ object DummyLinearStateSchemaV1 : MappedSchema(schemaFamily = DummyLinearStateSc /** * Dummy attributes */ - @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, diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt index f5f16c18ec..e339a7cb0d 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/vault/DummyLinearStateSchemaV2.kt @@ -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"))]) override var participants: MutableSet? = 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,