@dashevo/dapi-grpc 4.2.0-dev.1 → 4.2.0-dev.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build.rs +11 -0
- package/clients/drive/v0/nodejs/drive_pbjs.js +5959 -3606
- package/clients/platform/v0/nodejs/platform_pbjs.js +5959 -3606
- package/clients/platform/v0/nodejs/platform_protoc.js +4918 -2481
- package/clients/platform/v0/web/platform_pb.d.ts +319 -0
- package/clients/platform/v0/web/platform_pb.js +4918 -2481
- package/package.json +2 -2
- package/protos/platform/v0/platform.proto +304 -39
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dashevo/dapi-grpc",
|
|
3
|
-
"version": "4.2.0-dev.
|
|
3
|
+
"version": "4.2.0-dev.10",
|
|
4
4
|
"description": "DAPI GRPC definition file and generated clients",
|
|
5
5
|
"browser": "browser.js",
|
|
6
6
|
"main": "node.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"homepage": "https://github.com/dashevo/dapi-grpc#readme",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@dashevo/grpc-common": "4.2.0-dev.
|
|
48
|
+
"@dashevo/grpc-common": "4.2.0-dev.10",
|
|
49
49
|
"@dashevo/protobufjs": "6.10.5",
|
|
50
50
|
"@grpc/grpc-js": "^1.14.3",
|
|
51
51
|
"@improbable-eng/grpc-web": "^0.15.0",
|
|
@@ -594,6 +594,18 @@ message GetDocumentsRequest {
|
|
|
594
594
|
BETWEEN_EXCLUDE_RIGHT = 8;
|
|
595
595
|
IN = 9;
|
|
596
596
|
STARTS_WITH = 10;
|
|
597
|
+
// Time-range bucket selection (v1 only; the v0 CBOR surface is
|
|
598
|
+
// unaffected). `field` names a timestamp covered by a `timeRange`
|
|
599
|
+
// index. The operand is `WhereClause.time_range` (a
|
|
600
|
+
// `TimeRangeSelection`); `WhereClause.value` must be unset. For the
|
|
601
|
+
// relative selectors (`NEWEST` / `OLDEST`) the server resolves the
|
|
602
|
+
// selection to a bucket-start equality from current block time and
|
|
603
|
+
// the verifier re-derives the same bucket from the quorum-signed
|
|
604
|
+
// metadata time; `BY_START` names the window absolutely, so both
|
|
605
|
+
// sides read the start straight from the query — an ordinary
|
|
606
|
+
// index/count proof either way. See `timeRange` in the document
|
|
607
|
+
// meta-schema and `drive::query::resolve_time_range_bucket_clause`.
|
|
608
|
+
IN_TIME_RANGE = 11;
|
|
597
609
|
}
|
|
598
610
|
|
|
599
611
|
// Tagged scalar (or list) operand for a `WhereClause`. The
|
|
@@ -646,6 +658,54 @@ message GetDocumentsRequest {
|
|
|
646
658
|
}
|
|
647
659
|
}
|
|
648
660
|
|
|
661
|
+
// Operand of an `IN_TIME_RANGE` where clause: which window of a
|
|
662
|
+
// `timeRange` grid the query selects. Typed rather than riding
|
|
663
|
+
// `DocumentFieldValue` — the selection is not a field value, and a
|
|
664
|
+
// structured message keeps the selector an enum instead of a
|
|
665
|
+
// magic string.
|
|
666
|
+
//
|
|
667
|
+
// The relative selectors are resolved server-side: `NEWEST` is the
|
|
668
|
+
// freshest started window (largest grid start <= block time; the
|
|
669
|
+
// latest partial slice of history), `OLDEST` the oldest window still
|
|
670
|
+
// active at block time (a near-full trailing window of ~`range` —
|
|
671
|
+
// best for "trending over the last window"). The proof verifier
|
|
672
|
+
// re-derives the same window from the quorum-signed response
|
|
673
|
+
// metadata time, so neither side trusts the other's clock.
|
|
674
|
+
//
|
|
675
|
+
// `BY_START` names a window absolutely — any window, current or
|
|
676
|
+
// historic — by its start. `start_ms` is then required and must lie
|
|
677
|
+
// on the grid (`start_ms == phase + k * step`, in milliseconds);
|
|
678
|
+
// an unaligned start is rejected rather than snapped. A window with
|
|
679
|
+
// no documents (including one that has not started yet) is a
|
|
680
|
+
// provable empty answer, not an error. The relative selectors must
|
|
681
|
+
// NOT carry `start_ms` — one wire spelling per meaning.
|
|
682
|
+
message TimeRangeSelection {
|
|
683
|
+
enum Selector {
|
|
684
|
+
NEWEST = 0;
|
|
685
|
+
OLDEST = 1;
|
|
686
|
+
BY_START = 2;
|
|
687
|
+
}
|
|
688
|
+
// Names one of the field's declared grids, in the contract's own
|
|
689
|
+
// seconds — verbatim from the contract's `timeRange` declaration.
|
|
690
|
+
// Required when more than one `timeRange` grid buckets the field
|
|
691
|
+
// (the bare selector is ambiguous there and rejected); optional
|
|
692
|
+
// while exactly one grid does. A zero `phase` is the proto3
|
|
693
|
+
// default, matching the contract grammar where `phase` is an
|
|
694
|
+
// omittable key — every grid has exactly one wire spelling by
|
|
695
|
+
// construction.
|
|
696
|
+
message Grid {
|
|
697
|
+
uint64 range = 1 [jstype = JS_STRING];
|
|
698
|
+
uint64 step = 2 [jstype = JS_STRING];
|
|
699
|
+
uint64 phase = 3 [jstype = JS_STRING];
|
|
700
|
+
}
|
|
701
|
+
Selector selector = 1;
|
|
702
|
+
// `BY_START` only: the selected window's start, as a millisecond
|
|
703
|
+
// timestamp on the grid (see the message docstring). Rejected on
|
|
704
|
+
// the relative selectors.
|
|
705
|
+
optional uint64 start_ms = 2 [jstype = JS_STRING];
|
|
706
|
+
Grid grid = 3;
|
|
707
|
+
}
|
|
708
|
+
|
|
649
709
|
// Single `field <op> value` clause. The server reassembles a
|
|
650
710
|
// `Vec<WhereClause>` from the request's `where_clauses` field,
|
|
651
711
|
// runs the same `WhereClause::group_clauses` validator (rejects
|
|
@@ -654,10 +714,16 @@ message GetDocumentsRequest {
|
|
|
654
714
|
// then hands the structured clauses to the executor. Wire
|
|
655
715
|
// semantics are identical to v0's CBOR `[field, op, value]`
|
|
656
716
|
// triples — only the envelope differs.
|
|
717
|
+
//
|
|
718
|
+
// Exactly one operand field is set, keyed by the operator:
|
|
719
|
+
// `operator = IN_TIME_RANGE` carries its operand in `time_range`
|
|
720
|
+
// (`value` must be unset); every other operator carries `value`
|
|
721
|
+
// (`time_range` must be unset). Either mismatch is rejected.
|
|
657
722
|
message WhereClause {
|
|
658
723
|
string field = 1;
|
|
659
724
|
WhereOperator operator = 2;
|
|
660
725
|
DocumentFieldValue value = 3;
|
|
726
|
+
TimeRangeSelection time_range = 4;
|
|
661
727
|
}
|
|
662
728
|
|
|
663
729
|
// Per-group aggregate operand for the left side of a
|
|
@@ -703,12 +769,21 @@ message GetDocumentsRequest {
|
|
|
703
769
|
// before release rather than deprecated, because it invented
|
|
704
770
|
// non-SQL grammar for something SQL already expresses.
|
|
705
771
|
//
|
|
706
|
-
//
|
|
707
|
-
//
|
|
708
|
-
//
|
|
709
|
-
//
|
|
710
|
-
//
|
|
711
|
-
//
|
|
772
|
+
// **From protocol v14 a single `HAVING` clause is served as a
|
|
773
|
+
// bounded range read** (having-range mode): `SELECT <agg> GROUP BY
|
|
774
|
+
// p HAVING <agg> <op> <value> [ORDER BY <order-key> ASC|DESC]
|
|
775
|
+
// LIMIT n` answers from the same per-axis secondary as ranked
|
|
776
|
+
// mode, on an index declaring the matching ranked axis. The
|
|
777
|
+
// clause's aggregate must be the selected aggregate, the operator
|
|
778
|
+
// must describe one contiguous range (`NOT_EQUAL` / `IN` are
|
|
779
|
+
// rejected), and the optional `ORDER BY` picks the walk direction
|
|
780
|
+
// using the same order-key spelling as ranked mode: `f` for
|
|
781
|
+
// `SUM(f)` / `AVG(f)`, the `$count` sentinel for `COUNT(*)` —
|
|
782
|
+
// never an explicit `OrderClause.aggregate` target, which is
|
|
783
|
+
// rejected. See the supported-shape table on
|
|
784
|
+
// `GetDocumentsRequestV1`. On protocol v13 and earlier every
|
|
785
|
+
// non-empty `having` stays rejected with `Unsupported`, exactly as
|
|
786
|
+
// before.
|
|
712
787
|
//
|
|
713
788
|
// The operator set mirrors `WhereOperator` minus `STARTS_WITH`
|
|
714
789
|
// (prefix matching has no natural meaning against a scalar
|
|
@@ -849,12 +924,16 @@ message GetDocumentsRequest {
|
|
|
849
924
|
// It returns `ResultData.ranked`. See `order_by` and the
|
|
850
925
|
// supported-shape table below.
|
|
851
926
|
//
|
|
852
|
-
//
|
|
853
|
-
// `
|
|
854
|
-
//
|
|
855
|
-
//
|
|
856
|
-
//
|
|
857
|
-
//
|
|
927
|
+
// **Having-range mode** is served from protocol v14: a single
|
|
928
|
+
// `having` clause whose aggregate is the selected aggregate turns
|
|
929
|
+
// the request into a bounded range read over the same per-axis
|
|
930
|
+
// secondary ranked mode walks, answered in `ResultData.ranked`.
|
|
931
|
+
// On protocol v13 and earlier every non-empty `having` is rejected
|
|
932
|
+
// (`"HAVING clause is not yet implemented"`). `having` carries no
|
|
933
|
+
// ranking spelling: an earlier draft put cross-group ranking on the
|
|
934
|
+
// right of a `HAVING` (`HAVING AVG(grade) IN TOP(5)`) and that
|
|
935
|
+
// grammar was removed before release in favour of `ORDER BY` +
|
|
936
|
+
// `LIMIT`. See the supported-shape table below.
|
|
858
937
|
//
|
|
859
938
|
// **Supported shapes** (everything else rejects with a typed
|
|
860
939
|
// `QuerySyntaxError::Unsupported` so callers can detect un-wired
|
|
@@ -880,12 +959,16 @@ message GetDocumentsRequest {
|
|
|
880
959
|
// - a is the In field AND b is the range field, in that order → existing compound distinct shape; entries carry both `in_key` (= a's value) and `key` (= b's value).
|
|
881
960
|
//
|
|
882
961
|
// `select=<COUNT(*)|SUM(f)|AVG(f)>, group_by=[p], order_by=[<the selected aggregate>]` (protocol v14+) — **ranked mode**:
|
|
883
|
-
// - exactly one `group_by` property, exactly one `order_by` clause naming the select's aggregate (`f` for `SUM(f)` / `AVG(f)`, the `$count` sentinel for `COUNT(*)`), a `limit` in `1 ..= 100`, an optional `offset`, and no `
|
|
962
|
+
// - exactly one `group_by` property, exactly one `order_by` clause naming the select's aggregate (`f` for `SUM(f)` / `AVG(f)`, the `$count` sentinel for `COUNT(*)`), a `limit` in `1 ..= 100`, an optional `offset`, and no `having` / `start_at`, on an index declaring the matching `rankedCountable` / `rankedSummable` / `rankedAverageable` axis → ranked executor, answered in `ResultData.ranked`. On a single-property ranked index no `where` is accepted; on a compound ranked index every leading index property must be pinned (one clause per property, `group_by` names the trailing property) — `EQUAL` pins one prefix, and **at most one** clause may be `IN` (2..=10 distinct elements, `null` legal; a single-element `IN` normalizes to the equality pin; an element whose prefix was never written — at any depth of its pinned chain — contributes an empty branch, union semantics), fanning the walk out across one prefix branch per element and merging by `(aggregate, encoded prefix, group key)`; merged entries carry `in_key`. A non-zero `offset` is rejected together with `IN` (rank-skip is per-secondary; `OFFSET 0` is the offset-free request).
|
|
884
963
|
// - `DESC` is the "top n" reading (walk the axis from the largest aggregate down), `ASC` the "bottom n" reading. Worked example: `SELECT AVG(grade) GROUP BY restaurantId ORDER BY grade DESC LIMIT 1 OFFSET 4` is the 5th-best restaurant.
|
|
885
964
|
//
|
|
965
|
+
// `select=<COUNT(*)|SUM(f)|AVG(f)>, group_by=[p], having=[<the selected aggregate> <op> <value>]` (protocol v14+) — **having-range mode**:
|
|
966
|
+
// - exactly one `group_by` property, exactly one `having` clause whose aggregate is the select's aggregate, an operator describing one contiguous range (`EQUAL`, `GREATER_THAN[_OR_EQUALS]`, `LESS_THAN[_OR_EQUALS]`, `BETWEEN*`; `NOT_EQUAL` / `IN` rejected), a `limit` in `1 ..= 100`, an optional `order_by` naming the same aggregate (walk direction; ascending by default), and no `offset` / `start_at` / `start_after`, on an index declaring the matching ranked axis → having-range executor, answered in `ResultData.ranked`. `where` follows the same rule as ranked mode: none on a single-property ranked index; exactly one pin per leading index property on a compound ranked index, at most one of them an `IN` (2..=10 distinct elements; a never-written element contributes an empty branch) that fans the bound out across prefix branches and merges, entries carrying `in_key`.
|
|
967
|
+
// - no offset or cursor pagination: a page cut at `limit` continues only by tightening the bound past the last *distinct* aggregate value seen; a cut inside a tie (several groups sharing the boundary aggregate) cannot be continued, so size `limit` above the widest expected tie.
|
|
968
|
+
//
|
|
886
969
|
// **Rejected shapes** (return `Unsupported`):
|
|
887
|
-
// - any non-empty `having
|
|
888
|
-
// - at v14+: a ranked-shaped request carrying a `where`
|
|
970
|
+
// - any non-empty `having` on protocol v13 and earlier; at v14+, any `having` shape outside having-range mode above (multiple clauses, an aggregate other than the select's, `NOT_EQUAL` / `IN` as the having operator, a `where` shape other than the compound-index prefix pins above — equality pins plus at most one bounded `IN` — or a carried `offset` / cursor).
|
|
971
|
+
// - at v14+: a ranked-shaped request carrying a `where` shape other than the compound-index prefix pins above (an operator other than `EQUAL` or the one permitted `IN`, more than one `IN`, a `null` pin combined with an `IN`, a repeated or non-leading property, or a missing pin), a `start_at` / `start_after` cursor, more than one `order_by`, or an `order_by` naming anything but the selected aggregate.
|
|
889
972
|
// - `select=DOCUMENTS` with non-empty `group_by`.
|
|
890
973
|
// - `select=COUNT` with `group_by` on a field that is not constrained by an `In` or range where clause.
|
|
891
974
|
// - `select=COUNT` with `group_by.len() > 2`.
|
|
@@ -1084,12 +1167,13 @@ message GetDocumentsRequest {
|
|
|
1084
1167
|
// `HavingClause` / `HavingAggregate` for the operator and
|
|
1085
1168
|
// aggregate-function catalogs.
|
|
1086
1169
|
//
|
|
1087
|
-
// **
|
|
1088
|
-
//
|
|
1089
|
-
//
|
|
1090
|
-
//
|
|
1091
|
-
//
|
|
1092
|
-
//
|
|
1170
|
+
// **From protocol v14 a single clause is served** as a bounded
|
|
1171
|
+
// range read — having-range mode; see the message-level
|
|
1172
|
+
// supported-shape table. On v13 and earlier every non-empty
|
|
1173
|
+
// `having` is rejected with `Unsupported("HAVING clause is not
|
|
1174
|
+
// yet implemented")`. Multi-clause `HAVING COUNT(*) > 5 AND
|
|
1175
|
+
// SUM(amount) > 100` requests can still be constructed on the
|
|
1176
|
+
// wire, but stay rejected until a multi-clause evaluator lands.
|
|
1093
1177
|
//
|
|
1094
1178
|
// **`having` does not express ranking.** "The n highest-scoring
|
|
1095
1179
|
// groups" is `ORDER BY <the selected aggregate> DESC LIMIT n`
|
|
@@ -1107,13 +1191,17 @@ message GetDocumentsRequest {
|
|
|
1107
1191
|
// routes to the ranked executor (`group_by` + a single `order_by`
|
|
1108
1192
|
// naming the selected aggregate), `offset` skips that many ranks
|
|
1109
1193
|
// before the returned page, so `ORDER BY avg(grade) DESC LIMIT 1
|
|
1110
|
-
// OFFSET 4` is the 5th-best group. The skip is **
|
|
1111
|
-
//
|
|
1112
|
-
//
|
|
1113
|
-
// the
|
|
1114
|
-
// `RankedEntries.skipped`.
|
|
1115
|
-
//
|
|
1116
|
-
//
|
|
1194
|
+
// OFFSET 4` is the 5th-best group. The skip is **counted, not
|
|
1195
|
+
// walked**: grovedb descends on each subtree's aggregate count and
|
|
1196
|
+
// collapses whole subtrees that fit inside the remaining offset, so
|
|
1197
|
+
// the work stays `O(log n + k)` at any offset and the response
|
|
1198
|
+
// reports the skip it performed in `RankedEntries.skipped`. On a
|
|
1199
|
+
// proved request that count is additionally *attested* — committed
|
|
1200
|
+
// to by the proof and re-derived by the verifier; on an unproved
|
|
1201
|
+
// one it is the node's own report. See `RankedEntries.skipped`. There is deliberately no ceiling — an
|
|
1202
|
+
// offset of 4 and an offset of four billion cost the same *order*
|
|
1203
|
+
// of work — neither walks the region it skips — so there is no
|
|
1204
|
+
// denial-of-service lever a cap would close. An offset
|
|
1117
1205
|
// past the end of the ranking is a provable answer rather than an
|
|
1118
1206
|
// error: `entries` comes back empty and `skipped` is the ranking's
|
|
1119
1207
|
// whole population.
|
|
@@ -1124,6 +1212,127 @@ message GetDocumentsRequest {
|
|
|
1124
1212
|
// no ranked executor. Cursor pagination via `start_after` /
|
|
1125
1213
|
// `start_at` remains the supported way to page through documents.
|
|
1126
1214
|
optional uint32 offset = 12;
|
|
1215
|
+
|
|
1216
|
+
// Chained mode — a provable semi-join:
|
|
1217
|
+
// `SELECT * FROM <outer_document_type> WHERE $id IN
|
|
1218
|
+
// (SELECT <join_property> FROM <document_type> WHERE ...)`.
|
|
1219
|
+
//
|
|
1220
|
+
// Presence of this message selects chained mode: this request's
|
|
1221
|
+
// own `document_type` / `where_clauses` / `order_by` / `limit`
|
|
1222
|
+
// describe the INNER indexOnly query, and the outer half is
|
|
1223
|
+
// DERIVED from its results — the request carries no outer
|
|
1224
|
+
// clauses by design, and the verifier re-derives the outer
|
|
1225
|
+
// query from the proven inner values, so the join cannot be
|
|
1226
|
+
// steered by the responding node.
|
|
1227
|
+
//
|
|
1228
|
+
// Mode gates (rejected otherwise): the inner type must be
|
|
1229
|
+
// indexOnly and resolve to an index carrying `join_property`;
|
|
1230
|
+
// `join_property` must declare a same-contract
|
|
1231
|
+
// `refersTo: permanentDocument` targeting
|
|
1232
|
+
// `outer_document_type`; `limit` is REQUIRED (it bounds the
|
|
1233
|
+
// derived outer query — no server-default fallback) and capped
|
|
1234
|
+
// by the outer `$id IN` clause's 100-value limit; `selects`
|
|
1235
|
+
// must be empty or a single DOCUMENTS projection; `group_by`,
|
|
1236
|
+
// `having`, time-range clauses, cursors, and `offset` are all
|
|
1237
|
+
// rejected. Pagination is a range clause on `join_property`.
|
|
1238
|
+
//
|
|
1239
|
+
// The verifier needs nothing beyond the proof itself: it
|
|
1240
|
+
// subset-verifies the inner query against the merged proof to
|
|
1241
|
+
// extract the join values, re-derives the outer component, and
|
|
1242
|
+
// verifies the whole composition. A node that predates this
|
|
1243
|
+
// field ignores it (proto3 unknown field) and serves the plain
|
|
1244
|
+
// inner query — which FAILS CLOSED client-side: an inner-only
|
|
1245
|
+
// proof cannot satisfy the re-derived merged query for a
|
|
1246
|
+
// non-empty page, and an unproven response carries the wrong
|
|
1247
|
+
// ResultData variant.
|
|
1248
|
+
message ChainedJoin {
|
|
1249
|
+
// The inner property whose proven values become the outer
|
|
1250
|
+
// documents' `$id`s.
|
|
1251
|
+
string join_property = 1;
|
|
1252
|
+
// The joined document type — the `refersTo` target.
|
|
1253
|
+
string outer_document_type = 2;
|
|
1254
|
+
}
|
|
1255
|
+
ChainedJoin chained = 13;
|
|
1256
|
+
|
|
1257
|
+
// Composite mode — a page plus sub-queries DERIVED from its
|
|
1258
|
+
// results, answered as ONE merged proof over one state root.
|
|
1259
|
+
//
|
|
1260
|
+
// Presence of any `sub_queries` selects composite mode: this
|
|
1261
|
+
// request's own `data_contract_id` / `document_type` /
|
|
1262
|
+
// `where_clauses` / `order_by` / `limit` describe the PAGE, and
|
|
1263
|
+
// every sub-query's `IN` clause is derived by the node from the
|
|
1264
|
+
// page's (or an earlier sub-query's) proven documents. The
|
|
1265
|
+
// verifier re-derives every sub-query from the proven page with
|
|
1266
|
+
// the same builders, re-merges, and verifies the whole
|
|
1267
|
+
// composition — so the composition cannot be steered by the
|
|
1268
|
+
// responding node, and a node that predates this field (proto3
|
|
1269
|
+
// unknown field) serves a page-only proof that FAILS CLOSED
|
|
1270
|
+
// client-side.
|
|
1271
|
+
//
|
|
1272
|
+
// Mode gates (rejected otherwise): `limit` is REQUIRED on the
|
|
1273
|
+
// page (at most 100 — it bounds every derived clause); `selects`
|
|
1274
|
+
// must be empty or a single DOCUMENTS projection; `group_by`,
|
|
1275
|
+
// `having`, time-range clauses, cursors and `offset` are
|
|
1276
|
+
// rejected (paginate with a range clause on the page's ordering
|
|
1277
|
+
// property); `chained` and `sub_queries` are mutually exclusive.
|
|
1278
|
+
// See `SubQuery` for the per-sub-query rules.
|
|
1279
|
+
message SubQuery {
|
|
1280
|
+
// The contract this sub-query targets. Empty = the page's own
|
|
1281
|
+
// contract; otherwise any contract (profiles keyed by owner,
|
|
1282
|
+
// names keyed by identity).
|
|
1283
|
+
bytes data_contract_id = 1;
|
|
1284
|
+
string document_type = 2;
|
|
1285
|
+
// The FIXED clauses — everything but the derived `IN`, which
|
|
1286
|
+
// must not be named here.
|
|
1287
|
+
repeated WhereClause where_clauses = 3;
|
|
1288
|
+
// Ordering (documents only). Every component of the merged proof
|
|
1289
|
+
// walks in the page's direction: a bound field missing from here
|
|
1290
|
+
// is appended in that direction by the node and the verifier
|
|
1291
|
+
// alike, and an ordering that disagrees with the page's direction
|
|
1292
|
+
// is refused (turning a limited lookup around would change the
|
|
1293
|
+
// rows it returns).
|
|
1294
|
+
repeated OrderClause order_by = 4;
|
|
1295
|
+
// Documents lookups on a non-unique index REQUIRE a limit: it
|
|
1296
|
+
// caps the rows the lookup returns in total, in walk order, like
|
|
1297
|
+
// an ordinary IN query's limit (at most 100). Lookups already
|
|
1298
|
+
// bounded by their values (a unique index, or an indexOnly
|
|
1299
|
+
// terminal with every prefix fixed), by-id joins (completeness is
|
|
1300
|
+
// set equality) and counts take none.
|
|
1301
|
+
optional uint32 limit = 5;
|
|
1302
|
+
enum Kind {
|
|
1303
|
+
// The matching documents.
|
|
1304
|
+
DOCUMENTS = 0;
|
|
1305
|
+
// One count per derived value from the `countable` index
|
|
1306
|
+
// covering the fixed clauses plus the bound field. Must be
|
|
1307
|
+
// bound, and must not share its index path with a documents
|
|
1308
|
+
// component (the count reads the value trees the documents
|
|
1309
|
+
// query descends past).
|
|
1310
|
+
COUNT = 1;
|
|
1311
|
+
}
|
|
1312
|
+
Kind kind = 6;
|
|
1313
|
+
// The derived clause `<field> IN <values>`. Absent = a SIBLING:
|
|
1314
|
+
// an independent documents query proven under the same root.
|
|
1315
|
+
message Binding {
|
|
1316
|
+
// Whose proven documents supply the values: `0` = the page,
|
|
1317
|
+
// `n` = `sub_queries[n - 1]` (which must precede this one and
|
|
1318
|
+
// be a DOCUMENTS sub-query).
|
|
1319
|
+
uint32 source = 1;
|
|
1320
|
+
// The source property read off each document: `$id`,
|
|
1321
|
+
// `$ownerId`, or an identifier-typed property (dotted paths
|
|
1322
|
+
// reach nested properties). Documents without it contribute
|
|
1323
|
+
// nothing.
|
|
1324
|
+
string source_property = 2;
|
|
1325
|
+
// The sub-query field receiving the `IN` clause. `$id` makes
|
|
1326
|
+
// this a by-id JOIN: the source property must then declare
|
|
1327
|
+
// `refersTo: permanentDocument` targeting this document type,
|
|
1328
|
+
// so every derived id resolves and a missing document is an
|
|
1329
|
+
// invalid proof. Otherwise `$ownerId` or an indexed property
|
|
1330
|
+
// (a LOOKUP, where absence is a proven fact).
|
|
1331
|
+
string field = 3;
|
|
1332
|
+
}
|
|
1333
|
+
Binding bind = 7;
|
|
1334
|
+
}
|
|
1335
|
+
repeated SubQuery sub_queries = 14;
|
|
1127
1336
|
}
|
|
1128
1337
|
|
|
1129
1338
|
oneof version {
|
|
@@ -1372,6 +1581,14 @@ message GetDocumentsResponse {
|
|
|
1372
1581
|
// than hardcoding the literal.
|
|
1373
1582
|
double avg = 4;
|
|
1374
1583
|
}
|
|
1584
|
+
// The prefix branch this entry came from, set **only** on an
|
|
1585
|
+
// `IN`-pinned request (see the supported-shape table): the
|
|
1586
|
+
// encoded index-key bytes of the `IN` property's pinned value —
|
|
1587
|
+
// empty bytes for the `null` (absent-value) branch. Absent on
|
|
1588
|
+
// single-prefix responses. The same group key can legally appear
|
|
1589
|
+
// under two prefixes, so `(in_key, key)` is the entry's identity
|
|
1590
|
+
// on a merged page, exactly as on `CountEntry`.
|
|
1591
|
+
optional bytes in_key = 5;
|
|
1375
1592
|
}
|
|
1376
1593
|
|
|
1377
1594
|
// Ranked result entries. **Entry order IS the ranking order** —
|
|
@@ -1399,20 +1616,31 @@ message GetDocumentsResponse {
|
|
|
1399
1616
|
// group rather than the best.
|
|
1400
1617
|
//
|
|
1401
1618
|
// **When a requested offset exceeds the population**, `entries`
|
|
1402
|
-
// is empty and `skipped` is the ranking's
|
|
1619
|
+
// is empty and `skipped` is the ranking's *total* reported
|
|
1403
1620
|
// population — a positive, useful answer ("there are only 12
|
|
1404
1621
|
// groups") rather than a bare empty list.
|
|
1405
1622
|
//
|
|
1406
|
-
//
|
|
1407
|
-
//
|
|
1408
|
-
//
|
|
1409
|
-
//
|
|
1410
|
-
//
|
|
1411
|
-
//
|
|
1412
|
-
//
|
|
1413
|
-
//
|
|
1414
|
-
//
|
|
1415
|
-
//
|
|
1623
|
+
// Both paths report the same quantity: the offset you asked for
|
|
1624
|
+
// when the skip succeeded, and the ranking's total population
|
|
1625
|
+
// when the walk ran out of groups first. They no longer disagree
|
|
1626
|
+
// anywhere, including past the end.
|
|
1627
|
+
//
|
|
1628
|
+
// What differs is the *warrant*, not the value. On the proved
|
|
1629
|
+
// path the number is cryptographically attested — re-derived by
|
|
1630
|
+
// the verifier from the counted subtree commitments in the proof
|
|
1631
|
+
// bytes rather than trusted from this field — so a proving client
|
|
1632
|
+
// should use the verified value and ignore this one. On the
|
|
1633
|
+
// unproven path it is an **unverified claim**, exactly like the
|
|
1634
|
+
// entries beside it: it equals the attested value on an honest
|
|
1635
|
+
// node, and nothing forces a node to be honest. Read "the true
|
|
1636
|
+
// population" as "what this node says the population is".
|
|
1637
|
+
// Callers who need to trust it, rather than merely receive it,
|
|
1638
|
+
// must still prove.
|
|
1639
|
+
//
|
|
1640
|
+
// Do not assume this field equals the offset you requested. It
|
|
1641
|
+
// equals the offset only when the skip succeeded; when the walk
|
|
1642
|
+
// ran out of groups first it is smaller, and that is the answer
|
|
1643
|
+
// rather than an inconsistency.
|
|
1416
1644
|
optional uint64 skipped = 2 [jstype = JS_STRING];
|
|
1417
1645
|
}
|
|
1418
1646
|
|
|
@@ -1450,7 +1678,44 @@ message GetDocumentsResponse {
|
|
|
1450
1678
|
// `skipped` carries the page's starting rank — see
|
|
1451
1679
|
// `RankedEntries`.
|
|
1452
1680
|
RankedEntries ranked = 5;
|
|
1681
|
+
// Chained-mode result: both halves of the provable
|
|
1682
|
+
// semi-join, in inner order (the last inner projection's
|
|
1683
|
+
// join-property value is the pagination cursor; outer
|
|
1684
|
+
// documents are ordered by first appearance of their id
|
|
1685
|
+
// among the inner projections, deduplicated). Routed when
|
|
1686
|
+
// the request's `chained` message is present.
|
|
1687
|
+
ChainedDocuments chained = 6;
|
|
1688
|
+
// Composite-mode result: the page plus one result per
|
|
1689
|
+
// sub-query, in request order. Routed when the request
|
|
1690
|
+
// carries `sub_queries`.
|
|
1691
|
+
CompositeDocuments composite = 7;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
// Both halves of a chained (semi-join) query, each serialized
|
|
1696
|
+
// with its own document type.
|
|
1697
|
+
message ChainedDocuments {
|
|
1698
|
+
repeated bytes inner_documents = 1;
|
|
1699
|
+
repeated bytes outer_documents = 2;
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
// A composite query's page and per-sub-query results, documents
|
|
1703
|
+
// serialized with their own document type.
|
|
1704
|
+
message CompositeDocuments {
|
|
1705
|
+
// The page, exactly as the page query alone would return it.
|
|
1706
|
+
repeated bytes page_documents = 1;
|
|
1707
|
+
message SubQueryResult {
|
|
1708
|
+
oneof result {
|
|
1709
|
+
// DOCUMENTS: a by-id join in first-appearance order of the
|
|
1710
|
+
// derived ids; a lookup or sibling in query order.
|
|
1711
|
+
Documents documents = 1;
|
|
1712
|
+
// COUNT: one entry per derived value that has a count tree
|
|
1713
|
+
// (a value with no entry counts zero), keyed by the
|
|
1714
|
+
// value's index-key bytes.
|
|
1715
|
+
CountEntries counts = 2;
|
|
1716
|
+
}
|
|
1453
1717
|
}
|
|
1718
|
+
repeated SubQueryResult sub_results = 2;
|
|
1454
1719
|
}
|
|
1455
1720
|
|
|
1456
1721
|
oneof result {
|