mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
Merge branch 'release/os/4.4' into nnagy-os-4.4-os-4.5-20200511
This commit is contained in:
commit
e0b5319515
@ -302,7 +302,13 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
|||||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||||
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL
|
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL
|
||||||
) : this(participants, linearId?.map { it.id }, linearId?.mapNotNull { it.externalId }, status, contractStateTypes, relevancyStatus)
|
) : this(participants,
|
||||||
|
linearId?.map { it.id }.takeIf { it != null && it.isNotEmpty() },
|
||||||
|
linearId?.mapNotNull { it.externalId }.takeIf { it != null && it.isNotEmpty() },
|
||||||
|
status,
|
||||||
|
contractStateTypes,
|
||||||
|
relevancyStatus
|
||||||
|
)
|
||||||
|
|
||||||
// V3 c'tor
|
// V3 c'tor
|
||||||
@DeprecatedConstructorForDeserialization(version = 1)
|
@DeprecatedConstructorForDeserialization(version = 1)
|
||||||
|
@ -153,6 +153,18 @@ abstract class AbstractQueryCriteriaParser<Q : GenericQueryCriteria<Q,P>, in P:
|
|||||||
NOT_NULL -> criteriaBuilder.isNotNull(column)
|
NOT_NULL -> criteriaBuilder.isNotNull(column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given predicate if the provided `args` list is not empty
|
||||||
|
* If the list is empty it returns an always false predicate (1=0)
|
||||||
|
*/
|
||||||
|
protected fun checkIfListIsEmpty(args: List<Any>, criteriaBuilder: CriteriaBuilder, predicate: Predicate): Predicate {
|
||||||
|
return if (args.isEmpty()) {
|
||||||
|
criteriaBuilder.and(criteriaBuilder.equal(criteriaBuilder.literal(1), 0))
|
||||||
|
} else {
|
||||||
|
predicate
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HibernateAttachmentQueryCriteriaParser<T,R>(override val criteriaBuilder: CriteriaBuilder,
|
class HibernateAttachmentQueryCriteriaParser<T,R>(override val criteriaBuilder: CriteriaBuilder,
|
||||||
@ -215,7 +227,14 @@ class HibernateAttachmentQueryCriteriaParser<T,R>(override val criteriaBuilder:
|
|||||||
(criteria.contractClassNamesCondition as EqualityComparison<List<ContractClassName>>).rightLiteral
|
(criteria.contractClassNamesCondition as EqualityComparison<List<ContractClassName>>).rightLiteral
|
||||||
else emptyList()
|
else emptyList()
|
||||||
val joinDBAttachmentToContractClassNames = root.joinList<NodeAttachmentService.DBAttachment, ContractClassName>("contractClassNames")
|
val joinDBAttachmentToContractClassNames = root.joinList<NodeAttachmentService.DBAttachment, ContractClassName>("contractClassNames")
|
||||||
predicateSet.add(criteriaBuilder.and(joinDBAttachmentToContractClassNames.`in`(contractClassNames)))
|
|
||||||
|
predicateSet.add(
|
||||||
|
checkIfListIsEmpty(
|
||||||
|
args = contractClassNames,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(joinDBAttachmentToContractClassNames.`in`(contractClassNames))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
criteria.signersCondition?.let {
|
criteria.signersCondition?.let {
|
||||||
@ -224,7 +243,14 @@ class HibernateAttachmentQueryCriteriaParser<T,R>(override val criteriaBuilder:
|
|||||||
(criteria.signersCondition as EqualityComparison<List<PublicKey>>).rightLiteral
|
(criteria.signersCondition as EqualityComparison<List<PublicKey>>).rightLiteral
|
||||||
else emptyList()
|
else emptyList()
|
||||||
val joinDBAttachmentToSigners = root.joinList<NodeAttachmentService.DBAttachment, PublicKey>("signers")
|
val joinDBAttachmentToSigners = root.joinList<NodeAttachmentService.DBAttachment, PublicKey>("signers")
|
||||||
predicateSet.add(criteriaBuilder.and(joinDBAttachmentToSigners.`in`(signers)))
|
|
||||||
|
predicateSet.add(
|
||||||
|
checkIfListIsEmpty(
|
||||||
|
args = signers,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(joinDBAttachmentToSigners.`in`(signers))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
criteria.isSignedCondition?.let { isSigned ->
|
criteria.isSignedCondition?.let { isSigned ->
|
||||||
@ -290,14 +316,27 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
|||||||
|
|
||||||
// notary names
|
// notary names
|
||||||
criteria.notary?.let {
|
criteria.notary?.let {
|
||||||
predicateSet.add(criteriaBuilder.and(vaultStates.get<AbstractParty>("notary").`in`(criteria.notary)))
|
predicateSet.add(
|
||||||
|
checkIfListIsEmpty(
|
||||||
|
args = criteria.notary!!,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(vaultStates.get<AbstractParty>("notary").`in`(criteria.notary))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// state references
|
// state references
|
||||||
criteria.stateRefs?.let {
|
criteria.stateRefs?.let {
|
||||||
val persistentStateRefs = (criteria.stateRefs as List<StateRef>).map(::PersistentStateRef)
|
val persistentStateRefs = (criteria.stateRefs as List<StateRef>).map(::PersistentStateRef)
|
||||||
val compositeKey = vaultStates.get<PersistentStateRef>("stateRef")
|
val compositeKey = vaultStates.get<PersistentStateRef>("stateRef")
|
||||||
predicateSet.add(criteriaBuilder.and(compositeKey.`in`(persistentStateRefs)))
|
|
||||||
|
predicateSet.add(
|
||||||
|
checkIfListIsEmpty(
|
||||||
|
args = persistentStateRefs,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(compositeKey.`in`(persistentStateRefs))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// time constraints (recorded, consumed)
|
// time constraints (recorded, consumed)
|
||||||
@ -447,7 +486,14 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
|||||||
// owner
|
// owner
|
||||||
criteria.owner?.let {
|
criteria.owner?.let {
|
||||||
val owners = criteria.owner as List<AbstractParty>
|
val owners = criteria.owner as List<AbstractParty>
|
||||||
predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<AbstractParty>("owner").`in`(owners)))
|
|
||||||
|
predicateSet.add(
|
||||||
|
checkIfListIsEmpty(
|
||||||
|
args = owners,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(vaultFungibleStatesRoot.get<AbstractParty>("owner").`in`(owners))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// quantity
|
// quantity
|
||||||
@ -458,13 +504,27 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
|||||||
// issuer party
|
// issuer party
|
||||||
criteria.issuer?.let {
|
criteria.issuer?.let {
|
||||||
val issuerParties = criteria.issuer as List<AbstractParty>
|
val issuerParties = criteria.issuer as List<AbstractParty>
|
||||||
predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<AbstractParty>("issuer").`in`(issuerParties)))
|
|
||||||
|
predicateSet.add(
|
||||||
|
checkIfListIsEmpty(
|
||||||
|
args = issuerParties,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(vaultFungibleStatesRoot.get<AbstractParty>("issuer").`in`(issuerParties))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// issuer reference
|
// issuer reference
|
||||||
criteria.issuerRef?.let {
|
criteria.issuerRef?.let {
|
||||||
val issuerRefs = (criteria.issuerRef as List<OpaqueBytes>).map { it.bytes }
|
val issuerRefs = (criteria.issuerRef as List<OpaqueBytes>).map { it.bytes }
|
||||||
predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<ByteArray>("issuerRef").`in`(issuerRefs)))
|
|
||||||
|
predicateSet.add(
|
||||||
|
checkIfListIsEmpty(
|
||||||
|
args = issuerRefs,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(vaultFungibleStatesRoot.get<ByteArray>("issuerRef").`in`(issuerRefs))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (criteria.participants != null && criteria.exactParticipants != null)
|
if (criteria.participants != null && criteria.exactParticipants != null)
|
||||||
@ -498,14 +558,27 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
|||||||
// linear ids UUID
|
// linear ids UUID
|
||||||
criteria.uuid?.let {
|
criteria.uuid?.let {
|
||||||
val uuids = criteria.uuid as List<UUID>
|
val uuids = criteria.uuid as List<UUID>
|
||||||
predicateSet.add(criteriaBuilder.and(vaultLinearStatesRoot.get<UUID>("uuid").`in`(uuids)))
|
|
||||||
|
predicateSet.add(
|
||||||
|
checkIfListIsEmpty(
|
||||||
|
args = uuids,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(vaultLinearStatesRoot.get<UUID>("uuid").`in`(uuids))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// linear ids externalId
|
// linear ids externalId
|
||||||
criteria.externalId?.let {
|
criteria.externalId?.let {
|
||||||
val externalIds = criteria.externalId as List<String>
|
val externalIds = criteria.externalId as List<String>
|
||||||
if (externalIds.isNotEmpty())
|
|
||||||
predicateSet.add(criteriaBuilder.and(vaultLinearStatesRoot.get<String>("externalId").`in`(externalIds)))
|
predicateSet.add(
|
||||||
|
checkIfListIsEmpty(
|
||||||
|
args = externalIds,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(vaultLinearStatesRoot.get<String>("externalId").`in`(externalIds))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (criteria.participants != null && criteria.exactParticipants != null)
|
if (criteria.participants != null && criteria.exactParticipants != null)
|
||||||
@ -694,8 +767,11 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Get the persistent party entity.
|
// Get the persistent party entity.
|
||||||
commonPredicates[predicateID] = criteriaBuilder.and(
|
commonPredicates[predicateID] = checkIfListIsEmpty(
|
||||||
getPersistentPartyRoot().get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants))
|
args = participants,
|
||||||
|
criteriaBuilder = criteriaBuilder,
|
||||||
|
predicate = criteriaBuilder.and(getPersistentPartyRoot().get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the join for vault states to persistent entities (if this is not a Fungible nor Linear criteria query)
|
// Add the join for vault states to persistent entities (if this is not a Fungible nor Linear criteria query)
|
||||||
|
@ -258,6 +258,24 @@ class NodeAttachmentServiceTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `AttachmentsQueryCriteria returns empty resultset without errors if there is an empty list after the 'in' clause`() {
|
||||||
|
SelfCleaningDir().use { file ->
|
||||||
|
val contractJar = makeTestContractJar(file.path, "com.example.MyContract")
|
||||||
|
contractJar.read { storage.importAttachment(it, "uploaderB", "contract.jar") }
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
1,
|
||||||
|
storage.queryAttachments(AttachmentsQueryCriteria(contractClassNamesCondition = Builder.equal(listOf("com.example.MyContract")))).size
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
0,
|
||||||
|
storage.queryAttachments(AttachmentsQueryCriteria(contractClassNamesCondition = Builder.equal(emptyList()))).size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun `contract class, versioning and signing metadata can be used to search`() {
|
fun `contract class, versioning and signing metadata can be used to search`() {
|
||||||
SelfCleaningDir().use { file ->
|
SelfCleaningDir().use { file ->
|
||||||
|
@ -267,6 +267,31 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `VaultQueryCriteria returns empty resultset without errors if there is an empty list after the 'in' clause`() {
|
||||||
|
database.transaction {
|
||||||
|
val states = vaultFiller.fillWithSomeTestLinearStates(1, "TEST")
|
||||||
|
val stateRefs = states.states.map { it.ref }
|
||||||
|
|
||||||
|
val criteria = VaultQueryCriteria(notary = listOf(DUMMY_NOTARY))
|
||||||
|
val results = vaultService.queryBy<LinearState>(criteria)
|
||||||
|
assertThat(results.states).hasSize(1)
|
||||||
|
|
||||||
|
val emptyCriteria = VaultQueryCriteria(notary = emptyList())
|
||||||
|
val emptyResults = vaultService.queryBy<LinearState>(emptyCriteria)
|
||||||
|
assertThat(emptyResults.states).hasSize(0)
|
||||||
|
|
||||||
|
val stateCriteria = VaultQueryCriteria(stateRefs = stateRefs)
|
||||||
|
val stateResults = vaultService.queryBy<LinearState>(stateCriteria)
|
||||||
|
assertThat(stateResults.states).hasSize(1)
|
||||||
|
|
||||||
|
val emptyStateCriteria = VaultQueryCriteria(stateRefs = emptyList())
|
||||||
|
val emptyStateResults = vaultService.queryBy<LinearState>(emptyStateCriteria)
|
||||||
|
assertThat(emptyStateResults.states).hasSize(0)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Generic Query tests
|
/** Generic Query tests
|
||||||
(combining both FungibleState and LinearState contract types) */
|
(combining both FungibleState and LinearState contract types) */
|
||||||
|
|
||||||
@ -1823,6 +1848,33 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
|
|
||||||
/** LinearState tests */
|
/** LinearState tests */
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `LinearStateQueryCriteria returns empty resultset without errors if there is an empty list after the 'in' clause`() {
|
||||||
|
database.transaction {
|
||||||
|
val uid = UniqueIdentifier("999")
|
||||||
|
vaultFiller.fillWithSomeTestLinearStates(numberToCreate = 1, uniqueIdentifier = uid)
|
||||||
|
vaultFiller.fillWithSomeTestLinearStates(numberToCreate = 1, externalId = "1234")
|
||||||
|
|
||||||
|
val uuidCriteria = LinearStateQueryCriteria(uuid = listOf(uid.id))
|
||||||
|
val externalIdCriteria = LinearStateQueryCriteria(externalId = listOf("1234"))
|
||||||
|
|
||||||
|
val uuidResults = vaultService.queryBy<ContractState>(uuidCriteria)
|
||||||
|
val externalIdResults = vaultService.queryBy<ContractState>(externalIdCriteria)
|
||||||
|
|
||||||
|
assertThat(uuidResults.states).hasSize(1)
|
||||||
|
assertThat(externalIdResults.states).hasSize(1)
|
||||||
|
|
||||||
|
val uuidCriteriaEmpty = LinearStateQueryCriteria(uuid = emptyList())
|
||||||
|
val externalIdCriteriaEmpty = LinearStateQueryCriteria(externalId = emptyList())
|
||||||
|
|
||||||
|
val uuidResultsEmpty = vaultService.queryBy<ContractState>(uuidCriteriaEmpty)
|
||||||
|
val externalIdResultsEmpty = vaultService.queryBy<ContractState>(externalIdCriteriaEmpty)
|
||||||
|
|
||||||
|
assertThat(uuidResultsEmpty.states).hasSize(0)
|
||||||
|
assertThat(externalIdResultsEmpty.states).hasSize(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun `unconsumed linear heads for linearId without external Id`() {
|
fun `unconsumed linear heads for linearId without external Id`() {
|
||||||
database.transaction {
|
database.transaction {
|
||||||
@ -2030,6 +2082,46 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
|||||||
|
|
||||||
/** FungibleAsset tests */
|
/** FungibleAsset tests */
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `FungibleAssetQueryCriteria returns empty resultset without errors if there is an empty list after the 'in' clause`() {
|
||||||
|
database.transaction {
|
||||||
|
vaultFiller.fillWithSomeTestCash(100.DOLLARS, notaryServices, 1, MEGA_CORP.ref(0))
|
||||||
|
|
||||||
|
val ownerCriteria = FungibleAssetQueryCriteria(owner = listOf(MEGA_CORP))
|
||||||
|
val ownerResults = vaultService.queryBy<FungibleAsset<*>>(ownerCriteria)
|
||||||
|
|
||||||
|
assertThat(ownerResults.states).hasSize(1)
|
||||||
|
|
||||||
|
val emptyOwnerCriteria = FungibleAssetQueryCriteria(owner = emptyList())
|
||||||
|
val emptyOwnerResults = vaultService.queryBy<FungibleAsset<*>>(emptyOwnerCriteria)
|
||||||
|
|
||||||
|
assertThat(emptyOwnerResults.states).hasSize(0)
|
||||||
|
|
||||||
|
// Issuer field checks
|
||||||
|
val issuerCriteria = FungibleAssetQueryCriteria(issuer = listOf(MEGA_CORP))
|
||||||
|
val issuerResults = vaultService.queryBy<FungibleAsset<*>>(issuerCriteria)
|
||||||
|
|
||||||
|
assertThat(issuerResults.states).hasSize(1)
|
||||||
|
|
||||||
|
val emptyIssuerCriteria = FungibleAssetQueryCriteria(issuer = emptyList())
|
||||||
|
val emptyIssuerResults = vaultService.queryBy<FungibleAsset<*>>(emptyIssuerCriteria)
|
||||||
|
|
||||||
|
assertThat(emptyIssuerResults.states).hasSize(0)
|
||||||
|
|
||||||
|
// Issuer Ref field checks
|
||||||
|
val issuerRefCriteria = FungibleAssetQueryCriteria(issuerRef = listOf(MINI_CORP.ref(0).reference))
|
||||||
|
val issuerRefResults = vaultService.queryBy<FungibleAsset<*>>(issuerRefCriteria)
|
||||||
|
|
||||||
|
assertThat(issuerRefResults.states).hasSize(1)
|
||||||
|
|
||||||
|
val emptyIssuerRefCriteria = FungibleAssetQueryCriteria(issuerRef = emptyList())
|
||||||
|
val emptyIssuerRefResults = vaultService.queryBy<FungibleAsset<*>>(emptyIssuerRefCriteria)
|
||||||
|
|
||||||
|
assertThat(emptyIssuerRefResults.states).hasSize(0)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun `unconsumed fungible assets for specific issuer party and refs`() {
|
fun `unconsumed fungible assets for specific issuer party and refs`() {
|
||||||
database.transaction {
|
database.transaction {
|
||||||
|
Loading…
Reference in New Issue
Block a user