mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
CORDA-3182: Added additional property on VaultQueryCriteria for querying by account (#5423)
* Added an additional property on VaultQueryCriteria to specify an externalId/accountId when performing a vault query. Added logic in hibernate query criteria parser to handle the exernalId join and lookup. Added a test. * Fixed error in test. Fixed backwards incompatible changes. * Updated changelog. * Updated docs to remove incorrect instructions for querying by external ID.
This commit is contained in:
parent
c2057e0893
commit
99f4e4aac2
@ -81,6 +81,7 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
open val constraints: Set<Vault.ConstraintInfo> = emptySet()
|
||||
open val participants: List<AbstractParty>? = null
|
||||
abstract val contractStateTypes: Set<Class<out ContractState>>?
|
||||
open val externalIds: List<UUID> = emptyList()
|
||||
override fun visit(parser: IQueryCriteriaParser): Collection<Predicate> {
|
||||
return parser.parseCriteria(this)
|
||||
}
|
||||
@ -99,8 +100,24 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
override val relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
|
||||
override val constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
|
||||
override val constraints: Set<Vault.ConstraintInfo> = emptySet(),
|
||||
override val participants: List<AbstractParty>? = null
|
||||
override val participants: List<AbstractParty>? = null,
|
||||
override val externalIds: List<UUID> = emptyList()
|
||||
) : CommonQueryCriteria() {
|
||||
// V4 constructors.
|
||||
@DeprecatedConstructorForDeserialization(version = 7)
|
||||
constructor(
|
||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||
stateRefs: List<StateRef>? = null,
|
||||
notary: List<AbstractParty>? = null,
|
||||
softLockingCondition: SoftLockingCondition? = null,
|
||||
timeCondition: TimeCondition? = null,
|
||||
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
|
||||
constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
|
||||
constraints: Set<Vault.ConstraintInfo> = emptySet(),
|
||||
participants: List<AbstractParty>? = null
|
||||
) : this(status, contractStateTypes, stateRefs, notary, softLockingCondition, timeCondition, relevancyStatus, constraintTypes, constraints, participants, emptyList())
|
||||
|
||||
// V3 c'tors
|
||||
// These have to be manually specified as @JvmOverloads for some reason causes declaration clashes
|
||||
@DeprecatedConstructorForDeserialization(version = 6)
|
||||
@ -144,6 +161,34 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
fun withConstraintTypes(constraintTypes: Set<Vault.ConstraintInfo.Type>): VaultQueryCriteria = copy(constraintTypes = constraintTypes)
|
||||
fun withConstraints(constraints: Set<Vault.ConstraintInfo>): VaultQueryCriteria = copy(constraints = constraints)
|
||||
fun withParticipants(participants: List<AbstractParty>): VaultQueryCriteria = copy(participants = participants)
|
||||
fun withExternalIds(externalIds: List<UUID>): VaultQueryCriteria = copy(externalIds = externalIds)
|
||||
|
||||
fun copy(
|
||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||
stateRefs: List<StateRef>? = null,
|
||||
notary: List<AbstractParty>? = null,
|
||||
softLockingCondition: SoftLockingCondition? = null,
|
||||
timeCondition: TimeCondition? = null,
|
||||
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
|
||||
constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
|
||||
constraints: Set<Vault.ConstraintInfo> = emptySet(),
|
||||
participants: List<AbstractParty>? = null
|
||||
): VaultQueryCriteria {
|
||||
return VaultQueryCriteria(
|
||||
status,
|
||||
contractStateTypes,
|
||||
stateRefs,
|
||||
notary,
|
||||
softLockingCondition,
|
||||
timeCondition,
|
||||
relevancyStatus,
|
||||
constraintTypes,
|
||||
constraints,
|
||||
participants,
|
||||
externalIds
|
||||
)
|
||||
}
|
||||
|
||||
fun copy(
|
||||
status: Vault.StateStatus = this.status,
|
||||
@ -163,7 +208,8 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
relevancyStatus,
|
||||
constraintTypes,
|
||||
constraints,
|
||||
participants
|
||||
participants,
|
||||
externalIds
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -654,24 +654,5 @@ a view which maps each state to one or more external IDs. The entity relationshi
|
||||
|
||||
.. image:: resources/state-to-external-id.png
|
||||
|
||||
When performing a vault query, it is now possible to query for states by external ID using a custom query criteria.
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
UUID id = someExternalId;
|
||||
FieldInfo externalIdField = getField("externalId", VaultSchemaV1.StateToExternalId.class);
|
||||
CriteriaExpression externalId = Builder.equal(externalIdField, id);
|
||||
QueryCriteria query = new VaultCustomQueryCriteria(externalId);
|
||||
Vault.Page<StateType> results = vaultService.queryBy(StateType.class, query);
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val id: UUID = someExternalId
|
||||
val externalId = builder { VaultSchemaV1.StateToExternalId::externalId.equal(id) }
|
||||
val queryCriteria = QueryCriteria.VaultCustomQueryCriteria(externalId)
|
||||
val results = vaultService.queryBy<StateType>(queryCriteria).states
|
||||
|
||||
The ``VaultCustomQueryCriteria`` can also be combined with other query criteria, like custom schemas, for instance. See the vault query API
|
||||
examples above for how to combine ``QueryCriteria``.
|
||||
When performing a vault query, it is now possible to query for states by external ID using the ``externalIds`` parameter in
|
||||
``VaultQueryCriteria``.
|
@ -7,6 +7,9 @@ release, see :doc:`app-upgrade-notes`.
|
||||
Unreleased
|
||||
----------
|
||||
|
||||
* Introduced a new parameter ``externalIds: List<UUID>`` to ``VaultQueryCriteria`` which allows CorDapp developers to constrain queries
|
||||
to a specified set of external IDs.
|
||||
|
||||
* Introduced a new API on ``KeyManagementService`` which facilitates lookups of ``PublicKey`` s to ``externalId`` s (Account IDs).
|
||||
|
||||
* Introduced a new low level flow diagnostics tool: checkpoint agent (that can be used standalone or in conjunction with the ``dumpCheckpoints`` shell command).
|
||||
|
@ -659,6 +659,25 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
||||
}
|
||||
}
|
||||
|
||||
// External IDs.
|
||||
if (criteria.externalIds.isNotEmpty()) {
|
||||
val ids = criteria.externalIds
|
||||
|
||||
// Get the state to external id entity.
|
||||
val persistentStateToExternalIdEntity = VaultSchemaV1.StateToExternalId::class.java
|
||||
val entityRoot = rootEntities.getOrElse(persistentStateToExternalIdEntity) {
|
||||
val entityRoot = criteriaQuery.from(persistentStateToExternalIdEntity)
|
||||
rootEntities[persistentStateToExternalIdEntity] = entityRoot
|
||||
entityRoot
|
||||
}
|
||||
|
||||
// Add the join and external id predicates.
|
||||
val externalIdJoin = criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"), entityRoot.get<VaultSchemaV1.StateToExternalId>("compositeKey").get<PersistentStateRef>("stateRef"))
|
||||
val externalIdPredicate = criteriaBuilder.and(entityRoot.get<VaultSchemaV1.StateToExternalId>("externalId").`in`(ids))
|
||||
constraintPredicates.add(externalIdJoin)
|
||||
constraintPredicates.add(externalIdPredicate)
|
||||
}
|
||||
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,47 @@ class ExternalIdMappingTest {
|
||||
assertEquals(setOf(dummyStateOne, dummyStateTwo), resultTwo.map { it.state.data }.toSet())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `externalIds query criteria test`() {
|
||||
val vaultService = services.vaultService
|
||||
|
||||
// Create new external ID and two keys mapped to it.
|
||||
val id = UUID.randomUUID()
|
||||
val idTwo = UUID.randomUUID()
|
||||
val keyOne = services.keyManagementService.freshKeyAndCert(myself.identity, false, id)
|
||||
val keyTwo = services.keyManagementService.freshKeyAndCert(myself.identity, false, id)
|
||||
val keyThree = services.keyManagementService.freshKeyAndCert(myself.identity, false, idTwo)
|
||||
|
||||
// Create states with a public key assigned to the new external ID.
|
||||
val dummyStateOne = createDummyState(listOf(AnonymousParty(keyOne.owningKey)))
|
||||
val dummyStateTwo = createDummyState(listOf(AnonymousParty(keyTwo.owningKey)))
|
||||
val dummyStateThree = createDummyState(listOf(AnonymousParty(keyThree.owningKey)))
|
||||
|
||||
// This query should return two states!
|
||||
val result = database.transaction {
|
||||
vaultService.queryBy<DummyState>(QueryCriteria.VaultQueryCriteria(externalIds = listOf(id))).states
|
||||
}
|
||||
assertEquals(setOf(dummyStateOne, dummyStateTwo), result.map { it.state.data }.toSet())
|
||||
|
||||
// Should return nothing.
|
||||
val resultTwo = database.transaction {
|
||||
vaultService.queryBy<DummyState>(QueryCriteria.VaultQueryCriteria(externalIds = listOf(UUID.randomUUID()))).states
|
||||
}
|
||||
assertEquals(emptyList(), resultTwo)
|
||||
|
||||
// Should return one state.
|
||||
val resultThree = database.transaction {
|
||||
vaultService.queryBy<DummyState>(QueryCriteria.VaultQueryCriteria(externalIds = listOf(idTwo))).states
|
||||
}
|
||||
assertEquals(setOf(dummyStateThree), resultThree.map { it.state.data }.toSet())
|
||||
|
||||
// Should return all states.
|
||||
val resultFour = database.transaction {
|
||||
vaultService.queryBy<DummyState>(QueryCriteria.VaultQueryCriteria(externalIds = listOf())).states
|
||||
}
|
||||
assertEquals(setOf(dummyStateOne, dummyStateTwo, dummyStateThree), resultFour.map { it.state.data }.toSet())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `One state can be mapped to multiple externalIds`() {
|
||||
val vaultService = services.vaultService
|
||||
|
Loading…
Reference in New Issue
Block a user