mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
CORDA-3184 - Vault Query API enhancement: strict participants matching (#5524)
* Implementation of exact participant parsing for common query criteria. * Added more unit tests + fixed a minor bug. * Additional clean-up. * Add documentation and changelog entry. * Revert debug level SQL logging. * Fix detekt errors. * Fix docs formatting in code samples. * Updating baseline (false positives being reported). * Fix "Name shadowed: subRoot" code quality check. * Fix API stability checker failures. * Update baseline.
This commit is contained in:
parent
6ca4b589e2
commit
7dd6ecf96e
@ -8,6 +8,7 @@ import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.contracts.UniqueIdentifier
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.Vault
|
||||
import net.corda.core.schemas.StatePersistable
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
@ -82,6 +83,7 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
open val participants: List<AbstractParty>? = null
|
||||
abstract val contractStateTypes: Set<Class<out ContractState>>?
|
||||
open val externalIds: List<UUID> = emptyList()
|
||||
open val exactParticipants: List<AbstractParty>? = null
|
||||
override fun visit(parser: IQueryCriteriaParser): Collection<Predicate> {
|
||||
return parser.parseCriteria(this)
|
||||
}
|
||||
@ -101,8 +103,23 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
override val constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet(),
|
||||
override val constraints: Set<Vault.ConstraintInfo> = emptySet(),
|
||||
override val participants: List<AbstractParty>? = null,
|
||||
override val externalIds: List<UUID> = emptyList()
|
||||
override val externalIds: List<UUID> = emptyList(),
|
||||
override val exactParticipants: List<AbstractParty>? = null
|
||||
) : CommonQueryCriteria() {
|
||||
@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,
|
||||
externalIds: List<UUID> = emptyList()
|
||||
) : this(status, contractStateTypes, stateRefs, notary, softLockingCondition, timeCondition, relevancyStatus, constraintTypes, constraints, participants, externalIds, null)
|
||||
// V4 constructors.
|
||||
@DeprecatedConstructorForDeserialization(version = 7)
|
||||
constructor(
|
||||
@ -162,6 +179,36 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
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 withExactParticipants(exactParticipants: List<AbstractParty>): VaultQueryCriteria = copy(exactParticipants = exactParticipants)
|
||||
|
||||
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,
|
||||
externalIds: List<UUID> = emptyList()
|
||||
): VaultQueryCriteria {
|
||||
return VaultQueryCriteria(
|
||||
status,
|
||||
contractStateTypes,
|
||||
stateRefs,
|
||||
notary,
|
||||
softLockingCondition,
|
||||
timeCondition,
|
||||
relevancyStatus,
|
||||
constraintTypes,
|
||||
constraints,
|
||||
participants,
|
||||
externalIds,
|
||||
exactParticipants
|
||||
)
|
||||
}
|
||||
|
||||
fun copy(
|
||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||
@ -218,13 +265,24 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
* LinearStateQueryCriteria: provides query by attributes defined in [VaultSchema.VaultLinearState]
|
||||
*/
|
||||
data class LinearStateQueryCriteria(
|
||||
override val participants: List<AbstractParty>?,
|
||||
override val participants: List<AbstractParty>? = null,
|
||||
val uuid: List<UUID>? = null,
|
||||
val externalId: List<String>? = null,
|
||||
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||
override val contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||
override val relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL
|
||||
override val relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL,
|
||||
override val exactParticipants: List<AbstractParty>?
|
||||
) : CommonQueryCriteria() {
|
||||
// V4 c'tor
|
||||
@DeprecatedConstructorForDeserialization(version = 4)
|
||||
constructor(
|
||||
participants: List<AbstractParty>? = null,
|
||||
uuid: List<UUID>? = null,
|
||||
externalId: List<String>? = null,
|
||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||
relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL
|
||||
) : this(participants, uuid, externalId, status, contractStateTypes, relevancyStatus, null)
|
||||
// V3 c'tor
|
||||
@JvmOverloads
|
||||
@DeprecatedConstructorForDeserialization(version = 2)
|
||||
@ -265,6 +323,8 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
fun withStatus(status: Vault.StateStatus): LinearStateQueryCriteria = copy(status = status)
|
||||
fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): LinearStateQueryCriteria = copy(contractStateTypes = contractStateTypes)
|
||||
fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): LinearStateQueryCriteria = copy(relevancyStatus = relevancyStatus)
|
||||
fun withExactParticipants(exactParticipants: List<AbstractParty>): LinearStateQueryCriteria =
|
||||
copy(exactParticipants = exactParticipants)
|
||||
|
||||
fun copy(
|
||||
participants: List<AbstractParty>? = this.participants,
|
||||
@ -272,6 +332,23 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
externalId: List<String>? = this.externalId,
|
||||
status: Vault.StateStatus = this.status,
|
||||
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes
|
||||
): LinearStateQueryCriteria {
|
||||
return LinearStateQueryCriteria(
|
||||
participants,
|
||||
uuid,
|
||||
externalId,
|
||||
status,
|
||||
contractStateTypes
|
||||
)
|
||||
}
|
||||
|
||||
fun copy(
|
||||
participants: List<AbstractParty>? = this.participants,
|
||||
uuid: List<UUID>? = this.uuid,
|
||||
externalId: List<String>? = this.externalId,
|
||||
status: Vault.StateStatus = this.status,
|
||||
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes,
|
||||
relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus
|
||||
): LinearStateQueryCriteria {
|
||||
return LinearStateQueryCriteria(
|
||||
participants,
|
||||
@ -317,8 +394,21 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
val issuerRef: List<OpaqueBytes>? = null,
|
||||
override val status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||
override val contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||
override val relevancyStatus: Vault.RelevancyStatus
|
||||
override val relevancyStatus: Vault.RelevancyStatus,
|
||||
override val exactParticipants: List<AbstractParty>? = null
|
||||
) : CommonQueryCriteria() {
|
||||
// V4 c'tor
|
||||
@DeprecatedConstructorForDeserialization(version = 1)
|
||||
constructor(
|
||||
participants: List<AbstractParty>? = null,
|
||||
owner: List<AbstractParty>? = null,
|
||||
quantity: ColumnPredicate<Long>? = null,
|
||||
issuer: List<AbstractParty>? = null,
|
||||
issuerRef: List<OpaqueBytes>? = null,
|
||||
status: Vault.StateStatus = Vault.StateStatus.UNCONSUMED,
|
||||
contractStateTypes: Set<Class<out ContractState>>? = null,
|
||||
relevancyStatus: Vault.RelevancyStatus
|
||||
) : this(participants, owner, quantity, issuer, issuerRef, status, contractStateTypes, relevancyStatus, null)
|
||||
@JvmOverloads
|
||||
@DeprecatedConstructorForDeserialization(version = 1)
|
||||
constructor(
|
||||
@ -344,6 +434,30 @@ sealed class QueryCriteria : GenericQueryCriteria<QueryCriteria, IQueryCriteriaP
|
||||
fun withStatus(status: Vault.StateStatus): FungibleAssetQueryCriteria = copy(status = status)
|
||||
fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): FungibleAssetQueryCriteria = copy(contractStateTypes = contractStateTypes)
|
||||
fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): FungibleAssetQueryCriteria = copy(relevancyStatus = relevancyStatus)
|
||||
fun withExactParticipants(exactParticipants: List<AbstractParty>): FungibleAssetQueryCriteria
|
||||
= copy(exactParticipants = exactParticipants)
|
||||
|
||||
fun copy(
|
||||
participants: List<AbstractParty>? = this.participants,
|
||||
owner: List<AbstractParty>? = this.owner,
|
||||
quantity: ColumnPredicate<Long>? = this.quantity,
|
||||
issuer: List<AbstractParty>? = this.issuer,
|
||||
issuerRef: List<OpaqueBytes>? = this.issuerRef,
|
||||
status: Vault.StateStatus = this.status,
|
||||
contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes,
|
||||
relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus
|
||||
): FungibleAssetQueryCriteria {
|
||||
return FungibleAssetQueryCriteria(
|
||||
participants,
|
||||
owner,
|
||||
quantity,
|
||||
issuer,
|
||||
issuerRef,
|
||||
status,
|
||||
contractStateTypes,
|
||||
relevancyStatus
|
||||
)
|
||||
}
|
||||
|
||||
fun copy(
|
||||
participants: List<AbstractParty>? = this.participants,
|
||||
|
@ -755,6 +755,7 @@
|
||||
<ID>LargeClass:PropertyTest.kt$PropertyTest</ID>
|
||||
<ID>LargeClass:PropertyValidationTest.kt$PropertyValidationTest</ID>
|
||||
<ID>LargeClass:ProtonWrapperTests.kt$ProtonWrapperTests</ID>
|
||||
<ID>LargeClass:QueryCriteria.kt$QueryCriteria$VaultQueryCriteria : CommonQueryCriteria</ID>
|
||||
<ID>LargeClass:QueryCriteriaUtils.kt$Builder</ID>
|
||||
<ID>LargeClass:RPCClientProxyHandler.kt$RPCClientProxyHandler : InvocationHandler</ID>
|
||||
<ID>LargeClass:RPCDriver.kt$RPCDriverDSL : InternalDriverDSL</ID>
|
||||
@ -790,6 +791,7 @@
|
||||
<ID>LargeClass:X509UtilitiesTest.kt$X509UtilitiesTest</ID>
|
||||
<ID>LongMethod:EdDSATests.kt$EdDSATests$@Test fun `PureEdDSA Ed25519 test vectors`()</ID>
|
||||
<ID>LongMethod:FlowCookbook.kt$InitiatorFlow$@Suppress("RemoveExplicitTypeArguments") @Suspendable override fun call()</ID>
|
||||
<ID>LongMethod:HibernateQueryCriteriaParser.kt$HibernateQueryCriteriaParser$override fun parseCriteria(criteria: CommonQueryCriteria): Collection<Predicate></ID>
|
||||
<ID>LongMethod:IRSTests.kt$fun createDummyIRS(irsSelect: Int): InterestRateSwap.State</ID>
|
||||
<ID>LongMethod:RpcReconnectTests.kt$RpcReconnectTests$ @Test fun `test that the RPC client is able to reconnect and proceed after node failure, restart, or connection reset`()</ID>
|
||||
<ID>LongParameterList:AMQPSerializer.kt$AMQPSerializer$(obj: Any, data: Data, type: Type, output: SerializationOutput, context: SerializationContext, debugIndent: Int = 0)</ID>
|
||||
@ -870,7 +872,10 @@
|
||||
<ID>LongParameterList:ProcessUtilities.kt$ProcessUtilities$( arguments: List<String>, classPath: List<String> = defaultClassPath, workingDirectory: Path? = null, jdwpPort: Int? = null, extraJvmArguments: List<String> = emptyList(), maximumHeapSize: String? = null )</ID>
|
||||
<ID>LongParameterList:ProcessUtilities.kt$ProcessUtilities$( className: String, arguments: List<String>, classPath: List<String> = defaultClassPath, workingDirectory: Path? = null, jdwpPort: Int? = null, extraJvmArguments: List<String> = emptyList(), maximumHeapSize: String? = null )</ID>
|
||||
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.FungibleAssetQueryCriteria$( participants: List<AbstractParty>? = this.participants, owner: List<AbstractParty>? = this.owner, quantity: ColumnPredicate<Long>? = this.quantity, issuer: List<AbstractParty>? = this.issuer, issuerRef: List<OpaqueBytes>? = this.issuerRef, status: Vault.StateStatus = this.status, contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes )</ID>
|
||||
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.FungibleAssetQueryCriteria$( participants: List<AbstractParty>? = this.participants, owner: List<AbstractParty>? = this.owner, quantity: ColumnPredicate<Long>? = this.quantity, issuer: List<AbstractParty>? = this.issuer, issuerRef: List<OpaqueBytes>? = this.issuerRef, status: Vault.StateStatus = this.status, contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes, relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus )</ID>
|
||||
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.LinearStateQueryCriteria$( participants: List<AbstractParty>? = this.participants, uuid: List<UUID>? = this.uuid, externalId: List<String>? = this.externalId, status: Vault.StateStatus = this.status, contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes, relevancyStatus: Vault.RelevancyStatus = this.relevancyStatus )</ID>
|
||||
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( 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 )</ID>
|
||||
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( 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, externalIds: List<UUID> = emptyList() )</ID>
|
||||
<ID>LongParameterList:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( status: Vault.StateStatus = this.status, contractStateTypes: Set<Class<out ContractState>>? = this.contractStateTypes, stateRefs: List<StateRef>? = this.stateRefs, notary: List<AbstractParty>? = this.notary, softLockingCondition: SoftLockingCondition? = this.softLockingCondition, timeCondition: TimeCondition? = this.timeCondition )</ID>
|
||||
<ID>LongParameterList:RPCClient.kt$RPCClient$( rpcOpsClass: Class<I>, username: String, password: String, externalTrace: Trace? = null, impersonatedActor: Actor? = null, targetLegalIdentity: CordaX500Name? = null )</ID>
|
||||
<ID>LongParameterList:RPCDriver.kt$( isDebug: Boolean = false, driverDirectory: Path = Paths.get("build") / "rpc-driver" / getTimestampAsDirectoryName(), portAllocation: PortAllocation = globalPortAllocation, debugPortAllocation: PortAllocation = globalDebugPortAllocation, systemProperties: Map<String, String> = emptyMap(), useTestClock: Boolean = false, startNodesInProcess: Boolean = false, waitForNodesToFinish: Boolean = false, extraCordappPackagesToScan: List<String> = emptyList(), notarySpecs: List<NotarySpec> = emptyList(), externalTrace: Trace? = null, @Suppress("DEPRECATION") jmxPolicy: JmxPolicy = JmxPolicy(), networkParameters: NetworkParameters = testNetworkParameters(), notaryCustomOverrides: Map<String, Any?> = emptyMap(), inMemoryDB: Boolean = true, cordappsForAllNodes: Collection<TestCordappInternal>? = null, dsl: RPCDriverDSL.() -> A )</ID>
|
||||
@ -4459,6 +4464,7 @@
|
||||
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultCustomQueryCriteria$fun withContractStateTypes(contractStateTypes: Set<Class<out ContractState>>): VaultCustomQueryCriteria<L></ID>
|
||||
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultCustomQueryCriteria$fun withRelevancyStatus(relevancyStatus: Vault.RelevancyStatus): VaultCustomQueryCriteria<L></ID>
|
||||
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( 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 )</ID>
|
||||
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$( 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, externalIds: List<UUID> = emptyList() )</ID>
|
||||
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$@DeprecatedConstructorForDeserialization(version = 2) constructor(status: Vault.StateStatus, contractStateTypes: Set<Class<out ContractState>>?) : this(status, contractStateTypes, participants = null)</ID>
|
||||
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$@DeprecatedConstructorForDeserialization(version = 4) constructor(status: Vault.StateStatus, contractStateTypes: Set<Class<out ContractState>>?, stateRefs: List<StateRef>?, notary: List<AbstractParty>?) : this( status, contractStateTypes, stateRefs, notary, participants = null )</ID>
|
||||
<ID>MaxLineLength:QueryCriteria.kt$QueryCriteria.VaultQueryCriteria$@DeprecatedConstructorForDeserialization(version = 5) constructor(status: Vault.StateStatus, contractStateTypes: Set<Class<out ContractState>>?, stateRefs: List<StateRef>?, notary: List<AbstractParty>?, softLockingCondition: SoftLockingCondition?) : this( status, contractStateTypes, stateRefs, notary, softLockingCondition, participants = null )</ID>
|
||||
@ -5839,6 +5845,7 @@
|
||||
<ID>TooManyFunctions:PropertyValidationTest.kt$PropertyValidationTest</ID>
|
||||
<ID>TooManyFunctions:ProtonWrapperTests.kt$ProtonWrapperTests</ID>
|
||||
<ID>TooManyFunctions:PublicKeyToOwningIdentityCacheImplTest.kt$PublicKeyToOwningIdentityCacheImplTest</ID>
|
||||
<ID>TooManyFunctions:QueryCriteria.kt$QueryCriteria$FungibleAssetQueryCriteria : CommonQueryCriteria</ID>
|
||||
<ID>TooManyFunctions:QueryCriteria.kt$QueryCriteria$VaultQueryCriteria : CommonQueryCriteria</ID>
|
||||
<ID>TooManyFunctions:QueryCriteriaUtils.kt$Builder</ID>
|
||||
<ID>TooManyFunctions:RPCApi.kt$net.corda.nodeapi.RPCApi.kt</ID>
|
||||
|
@ -86,7 +86,8 @@ There are four implementations of this interface which can be chained together t
|
||||
|
||||
1. ``VaultQueryCriteria`` provides filterable criteria on attributes within the Vault states table: status (UNCONSUMED,
|
||||
CONSUMED), state reference(s), contract state type(s), notaries, soft locked states, timestamps (RECORDED, CONSUMED),
|
||||
state constraints (see :ref:`Constraint Types <implicit_constraint_types>`), relevancy (ALL, RELEVANT, NON_RELEVANT).
|
||||
state constraints (see :ref:`Constraint Types <implicit_constraint_types>`), relevancy (ALL, RELEVANT, NON_RELEVANT),
|
||||
participants (exact or any match).
|
||||
|
||||
.. note:: Sensible defaults are defined for frequently used attributes (status = UNCONSUMED, always include soft
|
||||
locked states).
|
||||
@ -94,7 +95,7 @@ There are four implementations of this interface which can be chained together t
|
||||
2. ``FungibleAssetQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core
|
||||
``FungibleAsset`` contract state interface, used to represent assets that are fungible, countable and issued by a
|
||||
specific party (eg. ``Cash.State`` and ``CommodityContract.State`` in the Corda finance module). Filterable
|
||||
attributes include: participants(s), owner(s), quantity, issuer party(s) and issuer reference(s).
|
||||
attributes include: participants (exact or any match), owner(s), quantity, issuer party(s) and issuer reference(s).
|
||||
|
||||
.. note:: All contract states that extend the ``FungibleAsset`` now automatically persist that interfaces common
|
||||
state attributes to the **vault_fungible_states** table.
|
||||
@ -102,7 +103,7 @@ There are four implementations of this interface which can be chained together t
|
||||
3. ``LinearStateQueryCriteria`` provides filterable criteria on attributes defined in the Corda Core ``LinearState``
|
||||
and ``DealState`` contract state interfaces, used to represent entities that continuously supersede themselves, all
|
||||
of which share the same ``linearId`` (e.g. trade entity states such as the ``IRSState`` defined in the SIMM
|
||||
valuation demo). Filterable attributes include: participant(s), linearId(s), uuid(s), and externalId(s).
|
||||
valuation demo). Filterable attributes include: participants (exact or any match), linearId(s), uuid(s), and externalId(s).
|
||||
|
||||
.. note:: All contract states that extend ``LinearState`` or ``DealState`` now automatically persist those
|
||||
interfaces common state attributes to the **vault_linear_states** table.
|
||||
@ -292,7 +293,7 @@ Query for unconsumed states for a given notary:
|
||||
:end-before: DOCEND VaultQueryExample4
|
||||
:dedent: 12
|
||||
|
||||
Query for unconsumed states for a given set of participants:
|
||||
Query for unconsumed states for a given set of participants (matches any state that contains at least one of the specified participants):
|
||||
|
||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||
:language: kotlin
|
||||
@ -300,6 +301,14 @@ Query for unconsumed states for a given set of participants:
|
||||
:end-before: DOCEND VaultQueryExample5
|
||||
:dedent: 12
|
||||
|
||||
Query for unconsumed states for a given set of participants (exactly matches only states that contain all specified participants):
|
||||
|
||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART VaultQueryExample51
|
||||
:end-before: DOCEND VaultQueryExample51
|
||||
:dedent: 12
|
||||
|
||||
Query for unconsumed states recorded between two time intervals:
|
||||
|
||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||
@ -364,7 +373,7 @@ Query for unconsumed deal states with deals references:
|
||||
:end-before: DOCEND VaultQueryExample10
|
||||
:dedent: 12
|
||||
|
||||
Query for unconsumed deal states with deals parties:
|
||||
Query for unconsumed deal states with deals parties (any match):
|
||||
|
||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||
:language: kotlin
|
||||
@ -372,6 +381,14 @@ Query for unconsumed deal states with deals parties:
|
||||
:end-before: DOCEND VaultQueryExample11
|
||||
:dedent: 12
|
||||
|
||||
Query for unconsumed deal states with deals parties (exact match):
|
||||
|
||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART VaultQueryExample52
|
||||
:end-before: DOCEND VaultQueryExample52
|
||||
:dedent: 12
|
||||
|
||||
Query for only relevant linear states in the vault:
|
||||
|
||||
.. literalinclude:: ../../node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
|
||||
|
@ -8,6 +8,8 @@ Unreleased
|
||||
----------
|
||||
* Moved and renamed the testing web server to the ``testing`` subproject. Also renamed the published artifact to ``corda-testserver.jar``.
|
||||
|
||||
* New Vault Query criteria to specify exact matches for specified participants.
|
||||
|
||||
* Support for Java 11 (compatibility mode). Please read https://github.com/corda/corda/pull/5356.
|
||||
|
||||
* Removed the RPC exception privacy feature. Previously, in production mode, the exceptions thrown on the node were stripped of all content
|
||||
|
@ -471,8 +471,12 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
||||
predicateSet.add(criteriaBuilder.and(vaultFungibleStatesRoot.get<ByteArray>("issuerRef").`in`(issuerRefs)))
|
||||
}
|
||||
|
||||
if (criteria.participants != null && criteria.exactParticipants != null)
|
||||
throw VaultQueryException("Cannot specify both participants (${criteria.participants}) and exactParticipants " +
|
||||
"(${criteria.exactParticipants}).")
|
||||
|
||||
// Participants.
|
||||
criteria.participants?.let {
|
||||
if (criteria.participants != null || criteria.exactParticipants != null) {
|
||||
// Join VaultFungibleState and PersistentParty tables (participant values are added to the common query criteria predicate)
|
||||
val statePartyToFungibleStatesJoin = criteriaBuilder.and(
|
||||
criteriaBuilder.equal(vaultFungibleStatesRoot.get<VaultSchemaV1.VaultFungibleStates>("stateRef"),
|
||||
@ -508,8 +512,12 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
||||
predicateSet.add(criteriaBuilder.and(vaultLinearStatesRoot.get<String>("externalId").`in`(externalIds)))
|
||||
}
|
||||
|
||||
if (criteria.participants != null && criteria.exactParticipants != null)
|
||||
throw VaultQueryException("Cannot specify both participants (${criteria.participants}) " +
|
||||
"and exactParticipants (${criteria.exactParticipants}).")
|
||||
|
||||
// Participants.
|
||||
criteria.participants?.let {
|
||||
if (criteria.participants != null || criteria.exactParticipants != null) {
|
||||
// Join VaultLinearState and PersistentParty tables (participant values are added to the common query criteria predicate)
|
||||
val statePartyToLinearStatesJoin = criteriaBuilder.and(
|
||||
criteriaBuilder.equal(vaultLinearStatesRoot.get<VaultSchemaV1.VaultLinearStates>("stateRef"),
|
||||
@ -702,6 +710,38 @@ class HibernateQueryCriteriaParser(val contractStateType: Class<out ContractStat
|
||||
}
|
||||
}
|
||||
|
||||
// Exact participants
|
||||
// Requires a tricky SQL query to ensure *only* exact matches are selected (eg. a transaction cannot have more nor less than the
|
||||
// exact participants specified in the query criteria).
|
||||
criteria.exactParticipants?.let {
|
||||
val exactParticipants = criteria.exactParticipants!!
|
||||
|
||||
// obtain all transactions where other participants are not present
|
||||
val subQueryNotExists = criteriaQuery.subquery(Tuple::class.java)
|
||||
val subRoot = subQueryNotExists.from(VaultSchemaV1.PersistentParty::class.java)
|
||||
subQueryNotExists.select(subRoot.get("x500Name"))
|
||||
subQueryNotExists.where(criteriaBuilder.and(
|
||||
criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"),
|
||||
subRoot.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))),
|
||||
criteriaBuilder.not(subRoot.get<VaultSchemaV1.PersistentParty>("x500Name").`in`(exactParticipants)))
|
||||
val subQueryNotExistsPredicate = criteriaBuilder.and(criteriaBuilder.not(criteriaBuilder.exists(subQueryNotExists)))
|
||||
constraintPredicates.add(subQueryNotExistsPredicate)
|
||||
|
||||
// join with transactions for each matching participant (only required where more than one)
|
||||
if (exactParticipants.size > 1)
|
||||
exactParticipants.forEach { participant ->
|
||||
val subQueryExists = criteriaQuery.subquery(Tuple::class.java)
|
||||
val subRootExists = subQueryExists.from(VaultSchemaV1.PersistentParty::class.java)
|
||||
subQueryExists.select(subRootExists.get("x500Name"))
|
||||
subQueryExists.where(criteriaBuilder.and(
|
||||
criteriaBuilder.equal(vaultStates.get<VaultSchemaV1.VaultStates>("stateRef"),
|
||||
subRootExists.get<VaultSchemaV1.PersistentParty>("compositeKey").get<PersistentStateRef>("stateRef"))),
|
||||
criteriaBuilder.equal(subRootExists.get<VaultSchemaV1.PersistentParty>("x500Name"), participant))
|
||||
val subQueryExistsPredicate = criteriaBuilder.and(criteriaBuilder.exists(subQueryExists))
|
||||
constraintPredicates.add(subQueryExistsPredicate)
|
||||
}
|
||||
}
|
||||
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
|
@ -241,6 +241,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
val criteria = VaultQueryCriteria(participants = listOf(BIG_CORP))
|
||||
val results = vaultService.queryBy<ContractState>(criteria)
|
||||
assertThat(results.states).hasSize(1)
|
||||
|
||||
// same query using strict participant matching
|
||||
val strictCriteria = VaultQueryCriteria().withExactParticipants(listOf(BIG_CORP))
|
||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
||||
assertThat(strictResults.states).hasSize(0) // all states include node identity (MEGA_CORP)
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,6 +259,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
val criteria = VaultQueryCriteria(participants = listOf(MINI_CORP, BIG_CORP))
|
||||
val results = vaultService.queryBy<ContractState>(criteria)
|
||||
assertThat(results.states).hasSize(2)
|
||||
|
||||
// same query using strict participant matching
|
||||
val strictCriteria = VaultQueryCriteria().withExactParticipants(listOf(MEGA_CORP, BIG_CORP))
|
||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
||||
assertThat(strictResults.states).hasSize(1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,10 +805,48 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
|
||||
vaultFiller.fillWithSomeTestLinearStates(2, "TEST", participants = listOf(MEGA_CORP, MINI_CORP))
|
||||
vaultFiller.fillWithSomeTestDeals(listOf("456"), participants = listOf(MEGA_CORP, BIG_CORP))
|
||||
vaultFiller.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(BIG_CORP))
|
||||
val criteria = LinearStateQueryCriteria(participants = listOf(BIG_CORP))
|
||||
vaultFiller.fillWithSomeTestDeals(listOf("123", "789"), participants = listOf(MEGA_CORP))
|
||||
|
||||
val criteria = LinearStateQueryCriteria(participants = listOf(MEGA_CORP))
|
||||
val results = vaultService.queryBy<ContractState>(criteria)
|
||||
assertThat(results.states).hasSize(3)
|
||||
assertThat(results.states).hasSize(5)
|
||||
|
||||
// same query using strict participant matching
|
||||
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(listOf(MEGA_CORP))
|
||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
||||
assertThat(strictResults.states).hasSize(2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unconsumed dummy states for exact single participant`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
|
||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, MINI_CORP))
|
||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, BIG_CORP))
|
||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP)) // exact match
|
||||
val strictCriteria = VaultQueryCriteria(exactParticipants = listOf(MEGA_CORP))
|
||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
||||
assertThat(strictResults.states).hasSize(1)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unconsumed dummy states for exact two participants`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY)
|
||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, MINI_CORP))
|
||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, BIG_CORP)) // exact match
|
||||
vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP))
|
||||
|
||||
val strictCriteria = VaultQueryCriteria(exactParticipants = listOf(MEGA_CORP, BIG_CORP))
|
||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
||||
assertThat(strictResults.states).hasSize(1)
|
||||
|
||||
// same query using strict participant matching (unordered list of participants)
|
||||
val strictCriteriaUnordered = VaultQueryCriteria(exactParticipants = listOf(BIG_CORP, MEGA_CORP))
|
||||
val strictResultsUnordered = vaultService.queryBy<ContractState>(strictCriteriaUnordered)
|
||||
assertThat(strictResultsUnordered.states).hasSize(1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -813,8 +861,19 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
val criteria = LinearStateQueryCriteria(participants = listOf(BIG_CORP, MINI_CORP))
|
||||
val results = vaultService.queryBy<ContractState>(criteria)
|
||||
// DOCEND VaultQueryExample5
|
||||
|
||||
assertThat(results.states).hasSize(3)
|
||||
|
||||
// same query using strict participant matching
|
||||
// DOCSTART VaultQueryExample51
|
||||
val strictCriteria = LinearStateQueryCriteria(exactParticipants = listOf(MEGA_CORP, BIG_CORP))
|
||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
||||
// DOCEND VaultQueryExample51
|
||||
assertThat(strictResults.states).hasSize(1)
|
||||
|
||||
// same query using strict participant matching (unordered list of participants)
|
||||
val strictCriteriaUnordered = LinearStateQueryCriteria(exactParticipants = listOf(BIG_CORP, MEGA_CORP))
|
||||
val strictResultsUnordered = vaultService.queryBy<ContractState>(strictCriteriaUnordered)
|
||||
assertThat(strictResultsUnordered.states).hasSize(1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1959,6 +2018,13 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
// DOCEND VaultQueryExample11
|
||||
|
||||
assertThat(results.states).hasSize(1)
|
||||
|
||||
// same query using strict participant matching
|
||||
// DOCSTART VaultQueryExample52
|
||||
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(parties)
|
||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
||||
// DOCEND VaultQueryExample52
|
||||
assertThat(strictResults.states).hasSize(0) // node identity included (MEGA_CORP)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2352,6 +2418,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
|
||||
assertThat(results.states).hasSize(1)
|
||||
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
|
||||
|
||||
// same query using strict participant matching
|
||||
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(listOf(ALICE))
|
||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
||||
assertThat(strictResults.states).hasSize(0) // all states include node identity (MEGA_CORP)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2369,6 +2440,11 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
|
||||
assertThat(results.states).hasSize(1)
|
||||
assertThat(results.states[0].state.data.linearId.externalId).isEqualTo("TEST1")
|
||||
|
||||
// same query using strict participant matching
|
||||
val strictCriteria = LinearStateQueryCriteria().withExactParticipants(listOf(MEGA_CORP, ALICE, BOB, CHARLIE))
|
||||
val strictResults = vaultService.queryBy<ContractState>(strictCriteria)
|
||||
assertThat(strictResults.states).hasSize(1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2401,7 +2477,7 @@ abstract class VaultQueryTestsBase : VaultQueryParties {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `composite query for fungible and linear states for multiple participants`() {
|
||||
fun `composite query for fungible, linear and dummy states for multiple participants`() {
|
||||
database.transaction {
|
||||
identitySvc.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
||||
identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY)
|
||||
|
Loading…
Reference in New Issue
Block a user