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,
|
||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||
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
|
||||
@DeprecatedConstructorForDeserialization(version = 1)
|
||||
|
@ -153,6 +153,18 @@ abstract class AbstractQueryCriteriaParser<Q : GenericQueryCriteria<Q,P>, in P:
|
||||
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,
|
||||
@ -215,7 +227,14 @@ class HibernateAttachmentQueryCriteriaParser<T,R>(override val criteriaBuilder:
|
||||
(criteria.contractClassNamesCondition as EqualityComparison<List<ContractClassName>>).rightLiteral
|
||||
else emptyList()
|
||||
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 {
|
||||
@ -224,7 +243,14 @@ class HibernateAttachmentQueryCriteriaParser<T,R>(override val criteriaBuilder:
|
||||
(criteria.signersCondition as EqualityComparison<List<PublicKey>>).rightLiteral
|
||||
else emptyList()
|
||||
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 ->
|
||||
@ -290,14 +316,27 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
||||
|
||||
// notary names
|
||||
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
|
||||
criteria.stateRefs?.let {
|
||||
val persistentStateRefs = (criteria.stateRefs as List<StateRef>).map(::PersistentStateRef)
|
||||
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)
|
||||
@ -447,7 +486,14 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
||||
// owner
|
||||
criteria.owner?.let {
|
||||
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
|
||||
@ -458,13 +504,27 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
||||
// issuer party
|
||||
criteria.issuer?.let {
|
||||
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
|
||||
criteria.issuerRef?.let {
|
||||
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)
|
||||
@ -498,14 +558,27 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
||||
// linear ids UUID
|
||||
criteria.uuid?.let {
|
||||
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
|
||||
criteria.externalId?.let {
|
||||
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)
|
||||
@ -694,8 +767,11 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
||||
}
|
||||
else {
|
||||
// Get the persistent party entity.
|
||||
commonPredicates[predicateID] = criteriaBuilder.and(
|
||||
getPersistentPartyRoot().get<VaultSchemaV1.PersistentParty>("x500Name").`in`(participants))
|
||||
commonPredicates[predicateID] = checkIfListIsEmpty(
|
||||
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)
|
||||
|
@ -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)
|
||||
fun `contract class, versioning and signing metadata can be used to search`() {
|
||||
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
|
||||
(combining both FungibleState and LinearState contract types) */
|
||||
|
||||
@ -1823,6 +1848,33 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
|
||||
/** 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)
|
||||
fun `unconsumed linear heads for linearId without external Id`() {
|
||||
database.transaction {
|
||||
@ -2030,6 +2082,46 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
|
||||
/** 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)
|
||||
fun `unconsumed fungible assets for specific issuer party and refs`() {
|
||||
database.transaction {
|
||||
|
Loading…
Reference in New Issue
Block a user