canton-pqs 0.3.2

Typed read client for the Daml Participant Query Store (PQS/Scribe): typed predicates compiled to parameterized JSONB queries.
Documentation

canton-pqs

A typed read client for the Daml Participant Query Store (PQS, served by Scribe).

Part of the Canton Rust SDK.

Two ways in, one set of types

PQS streams a participant's contracts into Postgres. It stores payloads in the Daml JSON encoding — which is what canton-daml implements — so a contract read here deserializes into the same generated type as one read from a transaction stream:

let contracts = pqs.active::<AppInstallRequest>().await?;
let payload: &AppInstallRequest = contracts[0].payload();

The template names itself: the qname PQS knows it by is PACKAGE_NAME:MODULE_NAME:ENTITY_NAME, read off the generated Contract impl, so nobody types a string. It is the package name, which is what survives a Smart Contract Upgrade rather than pinning one build.

No hand-written SQL, and no interpolation

Predicates compile to parameterized statements. Every caller-supplied value is a parameter — and so is every JSON field path, sent as text[] and applied with #>. The statement text depends on the shape of a query and never on its data, so a field name taken from user input is data Postgres never parses:

let sql = Query::<AppInstallRequest>::active()
    .filter(Predicate::eq(["meta", "values", "reason"], "renewal"))
    .filter(Predicate::signatory(&party))
    .limit(100)
    .compile();
// SELECT * FROM active($1) WHERE payload #> $2 = $3 AND $4 = ANY(signatories) LIMIT $5

Two details worth knowing:

  • Ordered comparisons on numbers are numeric. LF-JSON carries Int64 and Numeric as strings, so comparing an amount lexically would sort "9" after "10". Pass a number and the cast is applied; pass a string only where the field really is text.
  • Predicate::contains compiles to @>, the operator a GIN index on payload can serve — worth reaching for on a large store.

Features

Feature Default What it adds
tls off PqsClient::connect_tls, using the platform's root certificates.

Off by default because PQS is usually reached inside a trust boundary, and a crate that forces a TLS stack on a deployment that does not use one is charging for nothing.

Licence

Apache-2.0. See LICENSE.