@dashevo/dapi-grpc 4.1.0 → 4.2.0-dev.1
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/Cargo.toml +19 -8
- package/build.rs +11 -2
- package/clients/drive/v0/nodejs/drive_pbjs.js +668 -375
- package/clients/platform/v0/nodejs/platform_pbjs.js +668 -375
- package/clients/platform/v0/nodejs/platform_protoc.js +656 -289
- package/clients/platform/v0/web/platform_pb.d.ts +83 -42
- package/clients/platform/v0/web/platform_pb.js +656 -289
- package/package.json +2 -2
- package/protos/platform/v0/platform.proto +263 -93
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dashevo/dapi-grpc",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0-dev.1",
|
|
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.
|
|
48
|
+
"@dashevo/grpc-common": "4.2.0-dev.1",
|
|
49
49
|
"@dashevo/protobufjs": "6.10.5",
|
|
50
50
|
"@grpc/grpc-js": "^1.14.3",
|
|
51
51
|
"@improbable-eng/grpc-web": "^0.15.0",
|
|
@@ -661,9 +661,13 @@ message GetDocumentsRequest {
|
|
|
661
661
|
}
|
|
662
662
|
|
|
663
663
|
// Per-group aggregate operand for the left side of a
|
|
664
|
-
// `HavingClause
|
|
665
|
-
// `
|
|
666
|
-
//
|
|
664
|
+
// `HavingClause`, and the aggregate-function target of an
|
|
665
|
+
// `OrderClause`. Only the per-group aggregates live here —
|
|
666
|
+
// `HAVING` is a boolean predicate over one group's own aggregate,
|
|
667
|
+
// and nothing on this message reaches across groups. Cross-group
|
|
668
|
+
// ranking ("which groups score highest?") is expressed with SQL's
|
|
669
|
+
// ordering surface instead: `ORDER BY <the selected aggregate>
|
|
670
|
+
// DESC LIMIT n [OFFSET m]`. See `GetDocumentsRequestV1.order_by`.
|
|
667
671
|
//
|
|
668
672
|
// **Field semantics by function**:
|
|
669
673
|
// - `COUNT`: empty `field` means `COUNT(*)` (group cardinality);
|
|
@@ -682,58 +686,42 @@ message GetDocumentsRequest {
|
|
|
682
686
|
string field = 2;
|
|
683
687
|
}
|
|
684
688
|
|
|
685
|
-
//
|
|
686
|
-
// `HavingClause`. The ranking is computed over the set of
|
|
687
|
-
// group-aggregate results (one per `GROUP BY` row), so
|
|
688
|
-
// `HAVING COUNT(*) EQ MAX` selects groups whose count equals
|
|
689
|
-
// the maximum count across all groups, and
|
|
690
|
-
// `HAVING COUNT(*) IN TOP(5)` selects groups whose count is
|
|
691
|
-
// among the five largest. Concise way to express top-N /
|
|
692
|
-
// bottom-N selection without window functions or
|
|
693
|
-
// `ORDER BY` + `LIMIT`.
|
|
694
|
-
//
|
|
695
|
-
// **Operator compatibility**:
|
|
696
|
-
// - Scalar operators (`=`, `!=`, `<`, `<=`, `>`, `>=`) work
|
|
697
|
-
// with `MIN` / `MAX`. `TOP` / `BOTTOM` with scalar operators
|
|
698
|
-
// only make sense when `n=1` (the single largest / smallest);
|
|
699
|
-
// evaluation rejects other combinations as ambiguous.
|
|
700
|
-
// - `IN` works with `TOP(n)` / `BOTTOM(n)` for set membership.
|
|
701
|
-
// - `BETWEEN*` doesn't compose meaningfully with rankings and
|
|
702
|
-
// is rejected at evaluation time.
|
|
703
|
-
message HavingRanking {
|
|
704
|
-
enum Kind {
|
|
705
|
-
MIN = 0;
|
|
706
|
-
MAX = 1;
|
|
707
|
-
TOP = 2;
|
|
708
|
-
BOTTOM = 3;
|
|
709
|
-
}
|
|
710
|
-
Kind kind = 1;
|
|
711
|
-
// N-th rank for `TOP` / `BOTTOM` (1-indexed: `n=1` is the
|
|
712
|
-
// single largest / smallest). Required for those two kinds;
|
|
713
|
-
// must be unset for `MIN` / `MAX`. The wire allows setting
|
|
714
|
-
// it on `MIN` / `MAX` for forward compatibility, but
|
|
715
|
-
// evaluation rejects it as a malformed ranking.
|
|
716
|
-
optional uint64 n = 2 [jstype = JS_STRING];
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
// Single `HAVING <aggregate> <op> <right>` clause. Multiple
|
|
689
|
+
// Single `HAVING <aggregate> <op> <value>` clause. Multiple
|
|
720
690
|
// entries in `GetDocumentsRequestV1.having` combine with
|
|
721
691
|
// implicit AND — same semantics as multiple `where_clauses`
|
|
722
692
|
// entries. `HAVING COUNT(*) > 5 AND SUM(amount) > 100` is two
|
|
723
693
|
// `HavingClause` rows, not a tree.
|
|
724
694
|
//
|
|
695
|
+
// **`HAVING` is a boolean per-group predicate and nothing else.**
|
|
696
|
+
// Its right operand is always a literal `DocumentFieldValue`; it
|
|
697
|
+
// never names another group or the set of groups. Cross-group
|
|
698
|
+
// ranking — "the 5 highest-scoring groups" — is `ORDER BY <the
|
|
699
|
+
// selected aggregate> DESC LIMIT 5`, exactly as in SQL, and is
|
|
700
|
+
// served by the ranked executor (protocol v14+). An earlier draft
|
|
701
|
+
// of this surface carried the ranking on the right of a `HAVING`
|
|
702
|
+
// (`HAVING AVG(grade) IN TOP(5)`); that spelling was removed
|
|
703
|
+
// before release rather than deprecated, because it invented
|
|
704
|
+
// non-SQL grammar for something SQL already expresses.
|
|
705
|
+
//
|
|
706
|
+
// **`HAVING` cannot yet combine with an aggregate `ORDER BY`.**
|
|
707
|
+
// The ranked executor reads a pre-sorted per-axis secondary and
|
|
708
|
+
// has no way to drop groups from the middle of that walk, so a
|
|
709
|
+
// request carrying both a non-empty `having` and a ranking
|
|
710
|
+
// `order_by` is rejected with `Unsupported` rather than served
|
|
711
|
+
// with one of the two silently ignored.
|
|
712
|
+
//
|
|
725
713
|
// The operator set mirrors `WhereOperator` minus `STARTS_WITH`
|
|
726
714
|
// (prefix matching has no natural meaning against a scalar
|
|
727
715
|
// aggregate result, even a string-typed one). `BETWEEN*` and
|
|
728
716
|
// `IN` operand semantics match `WhereOperator`: `BETWEEN*`
|
|
729
717
|
// expects a 2-element `DocumentFieldValue.list` carrying
|
|
730
718
|
// `[lower, upper]`, and `IN` expects a `list` of candidate
|
|
731
|
-
// values
|
|
719
|
+
// values.
|
|
732
720
|
//
|
|
733
|
-
// The `right` oneof
|
|
734
|
-
// `DocumentFieldValue`
|
|
735
|
-
//
|
|
736
|
-
//
|
|
721
|
+
// The `right` oneof exists (rather than a bare
|
|
722
|
+
// `DocumentFieldValue` field) so the "unset right operand" case
|
|
723
|
+
// stays distinguishable from "the literal null value"; the wire
|
|
724
|
+
// rejects an unset `right`.
|
|
737
725
|
message HavingClause {
|
|
738
726
|
enum Operator {
|
|
739
727
|
EQUAL = 0;
|
|
@@ -752,33 +740,65 @@ message GetDocumentsRequest {
|
|
|
752
740
|
Operator operator = 2;
|
|
753
741
|
oneof right {
|
|
754
742
|
DocumentFieldValue value = 3;
|
|
755
|
-
HavingRanking ranking = 4;
|
|
756
743
|
}
|
|
757
744
|
}
|
|
758
745
|
|
|
759
|
-
// Single `ORDER BY
|
|
746
|
+
// Single `ORDER BY <target> <direction>` clause. Multi-field
|
|
760
747
|
// ordering is expressed by repeating this message at the
|
|
761
748
|
// request level (`repeated OrderClause order_by = 4`), matching
|
|
762
749
|
// SQL's `ORDER BY a ASC, b DESC` shape.
|
|
763
|
-
// Single ORDER BY entry. Multi-entry ordering is expressed by
|
|
764
|
-
// repeating this message at the request level.
|
|
765
750
|
//
|
|
766
751
|
// The `target` oneof carries either a plain field name
|
|
767
752
|
// (`ORDER BY field`) or an aggregate function applied to a
|
|
768
|
-
// field (`ORDER BY COUNT(*)`, `ORDER BY SUM(amount)`)
|
|
769
|
-
//
|
|
770
|
-
//
|
|
771
|
-
//
|
|
772
|
-
//
|
|
773
|
-
//
|
|
753
|
+
// field (`ORDER BY COUNT(*)`, `ORDER BY SUM(amount)`).
|
|
754
|
+
//
|
|
755
|
+
// **Two distinct roles ride the `field` target.**
|
|
756
|
+
//
|
|
757
|
+
// 1. *Row ordering* — `select = DOCUMENTS`. `field` names a
|
|
758
|
+
// document property and the matched rows come back in that
|
|
759
|
+
// order. This is v0's behaviour, unchanged.
|
|
760
|
+
//
|
|
761
|
+
// 2. *Aggregate ordering* — the **ranked** surface (protocol
|
|
762
|
+
// v14+). With a `GROUP BY` and a single aggregate `select`,
|
|
763
|
+
// exactly one `order_by` clause naming that select's
|
|
764
|
+
// aggregate orders the *groups* by their aggregate value and
|
|
765
|
+
// routes the request to the ranked executor:
|
|
774
766
|
//
|
|
775
|
-
//
|
|
776
|
-
//
|
|
777
|
-
//
|
|
778
|
-
//
|
|
767
|
+
// ```text
|
|
768
|
+
// SELECT AVG(grade) GROUP BY restaurantId
|
|
769
|
+
// ORDER BY grade DESC LIMIT 3 -- 3 best restaurants
|
|
770
|
+
// SELECT COUNT(*) GROUP BY restaurantId
|
|
771
|
+
// ORDER BY $count DESC LIMIT 10 OFFSET 10 -- busiest, page 2
|
|
772
|
+
// ```
|
|
773
|
+
//
|
|
774
|
+
// `SUM(f)` / `AVG(f)` are named by `f` — the same property the
|
|
775
|
+
// projection aggregates, which is how `ORDER BY avg(grade)`
|
|
776
|
+
// reads once `SELECT` has already fixed the function.
|
|
777
|
+
// `COUNT(*)` aggregates no property, so it is named by the
|
|
778
|
+
// reserved sentinel **`$count`**. The `$` prefix is what keeps
|
|
779
|
+
// the sentinel from colliding with a real document property:
|
|
780
|
+
// document properties cannot start with `$` (that namespace is
|
|
781
|
+
// the system fields' `$id` / `$ownerId` / …), so `$count` can
|
|
782
|
+
// never be mistaken for a column. `DESC` is the "top n"
|
|
783
|
+
// reading, `ASC` the "bottom n" reading.
|
|
784
|
+
//
|
|
785
|
+
// An `order_by` naming anything other than the selected
|
|
786
|
+
// aggregate — a second clause, the `GROUP BY` property, an
|
|
787
|
+
// unrelated field — is rejected rather than normalized: it
|
|
788
|
+
// asks for an ordering the ranked secondary cannot produce.
|
|
789
|
+
//
|
|
790
|
+
// **Aggregate target still rejected** with
|
|
791
|
+
// `Unsupported("ORDER BY on aggregate keys is not yet
|
|
792
|
+
// implemented")`. It is the *explicit* spelling of role 2
|
|
793
|
+
// (`ORDER BY AVG(grade)` rather than `ORDER BY grade` under a
|
|
794
|
+
// `SELECT AVG(grade)`) and is wire-stable so it can start being
|
|
795
|
+
// evaluated without another version bump; today the field-target
|
|
796
|
+
// spelling above is the one the ranked executor reads.
|
|
779
797
|
message OrderClause {
|
|
780
798
|
oneof target {
|
|
781
|
-
// Plain field name. Today's evaluated form
|
|
799
|
+
// Plain field name. Today's evaluated form — a document
|
|
800
|
+
// property for row ordering, or the selected aggregate's
|
|
801
|
+
// property (`$count` for `COUNT(*)`) for aggregate ordering.
|
|
782
802
|
string field = 1;
|
|
783
803
|
// Aggregate function applied to a field, sorted by the
|
|
784
804
|
// per-group result. `function = DOCUMENTS` is invalid
|
|
@@ -823,12 +843,18 @@ message GetDocumentsRequest {
|
|
|
823
843
|
// other shapes return `Unsupported` (see supported-shape table
|
|
824
844
|
// below).
|
|
825
845
|
//
|
|
826
|
-
//
|
|
827
|
-
//
|
|
828
|
-
// `
|
|
829
|
-
//
|
|
830
|
-
//
|
|
831
|
-
//
|
|
846
|
+
// **Ranked mode** is served from protocol v14 and is selected by
|
|
847
|
+
// `group_by` + a single `order_by` naming the selected aggregate —
|
|
848
|
+
// SQL's own top-n spelling, `ORDER BY <agg> DESC LIMIT n OFFSET m`.
|
|
849
|
+
// It returns `ResultData.ranked`. See `order_by` and the
|
|
850
|
+
// supported-shape table below.
|
|
851
|
+
//
|
|
852
|
+
// `having` is a boolean per-group predicate and is **still**
|
|
853
|
+
// `Unsupported` at every protocol version, ranked mode or not
|
|
854
|
+
// (`"HAVING clause is not yet implemented"`). It carries no ranking
|
|
855
|
+
// spelling: an earlier draft put cross-group ranking on the right of
|
|
856
|
+
// a `HAVING` (`HAVING AVG(grade) IN TOP(5)`) and that grammar was
|
|
857
|
+
// removed before release in favour of `ORDER BY` + `LIMIT`.
|
|
832
858
|
//
|
|
833
859
|
// **Supported shapes** (everything else rejects with a typed
|
|
834
860
|
// `QuerySyntaxError::Unsupported` so callers can detect un-wired
|
|
@@ -853,8 +879,13 @@ message GetDocumentsRequest {
|
|
|
853
879
|
// `select=COUNT, group_by=[a, b]`:
|
|
854
880
|
// - 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).
|
|
855
881
|
//
|
|
882
|
+
// `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 `where` / `having` / `start_at`, on an index declaring the matching `rankedCountable` / `rankedSummable` / `rankedAverageable` axis → ranked executor, answered in `ResultData.ranked`.
|
|
884
|
+
// - `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
|
+
//
|
|
856
886
|
// **Rejected shapes** (return `Unsupported`):
|
|
857
|
-
// - any non-empty `having
|
|
887
|
+
// - any non-empty `having`, at every protocol version.
|
|
888
|
+
// - at v14+: a ranked-shaped request carrying a `where` clause, a `start_at` / `start_after` cursor, more than one `order_by`, or an `order_by` naming anything but the selected aggregate.
|
|
858
889
|
// - `select=DOCUMENTS` with non-empty `group_by`.
|
|
859
890
|
// - `select=COUNT` with `group_by` on a field that is not constrained by an `In` or range where clause.
|
|
860
891
|
// - `select=COUNT` with `group_by.len() > 2`.
|
|
@@ -927,11 +958,11 @@ message GetDocumentsRequest {
|
|
|
927
958
|
AVG = 3;
|
|
928
959
|
// Per-group MIN / MAX — `SELECT MIN(field) GROUP BY
|
|
929
960
|
// category` returns the smallest `field` value in each
|
|
930
|
-
// category.
|
|
931
|
-
// `
|
|
932
|
-
//
|
|
933
|
-
//
|
|
934
|
-
//
|
|
961
|
+
// category. These operate over the row values *within*
|
|
962
|
+
// each group, the same way `SUM` and `AVG` do; they are
|
|
963
|
+
// not a cross-group ranking. To pick out the extreme
|
|
964
|
+
// *group*, order by the aggregate instead:
|
|
965
|
+
// `ORDER BY <agg> ASC|DESC LIMIT 1` (see `order_by`).
|
|
935
966
|
MIN = 4;
|
|
936
967
|
MAX = 5;
|
|
937
968
|
}
|
|
@@ -1044,33 +1075,54 @@ message GetDocumentsRequest {
|
|
|
1044
1075
|
// message-level docstring for the supported-shape table.
|
|
1045
1076
|
repeated string group_by = 10;
|
|
1046
1077
|
|
|
1047
|
-
// SQL `HAVING` clauses — aggregate filters that
|
|
1048
|
-
// grouped rows produced by `select
|
|
1049
|
-
// wire shape is `HavingClause`, not
|
|
1050
|
-
// HAVING evaluates against per-group
|
|
1051
|
-
// (`COUNT
|
|
1052
|
-
//
|
|
1053
|
-
//
|
|
1054
|
-
//
|
|
1078
|
+
// SQL `HAVING` clauses — **boolean** aggregate filters that
|
|
1079
|
+
// apply to the grouped rows produced by `select=<COUNT|SUM|AVG>,
|
|
1080
|
+
// group_by=[…]`. The wire shape is `HavingClause`, not
|
|
1081
|
+
// `WhereClause`, because HAVING evaluates against per-group
|
|
1082
|
+
// aggregates (`COUNT` / `SUM` / `AVG`) rather than row field
|
|
1083
|
+
// values. Multiple entries combine with implicit AND. See
|
|
1084
|
+
// `HavingClause` / `HavingAggregate` for the operator and
|
|
1085
|
+
// aggregate-function catalogs.
|
|
1055
1086
|
//
|
|
1056
|
-
// **
|
|
1057
|
-
// `Unsupported("HAVING clause is not yet
|
|
1058
|
-
// wire shape
|
|
1059
|
-
// can
|
|
1060
|
-
//
|
|
1061
|
-
//
|
|
1062
|
-
//
|
|
1087
|
+
// **Every non-empty `having` is rejected**, at every protocol
|
|
1088
|
+
// version, with `Unsupported("HAVING clause is not yet
|
|
1089
|
+
// implemented")`. The wire shape ships ahead of evaluation so
|
|
1090
|
+
// callers can construct full `HAVING COUNT(*) > 5 AND
|
|
1091
|
+
// SUM(amount) > 100` requests in their builders, and so the
|
|
1092
|
+
// capability can land without another version bump.
|
|
1093
|
+
//
|
|
1094
|
+
// **`having` does not express ranking.** "The n highest-scoring
|
|
1095
|
+
// groups" is `ORDER BY <the selected aggregate> DESC LIMIT n`
|
|
1096
|
+
// (see `order_by`), which *is* served, from protocol v14. An
|
|
1097
|
+
// earlier draft of this surface spelled it
|
|
1098
|
+
// `HAVING AVG(grade) IN TOP(5)`; that grammar was removed
|
|
1099
|
+
// before release rather than deprecated.
|
|
1063
1100
|
repeated HavingClause having = 11;
|
|
1064
1101
|
|
|
1065
1102
|
// Row-based pagination offset, on top of the cursor-based
|
|
1066
1103
|
// `start_after` / `start_at` pagination. `OFFSET N` skips the
|
|
1067
|
-
// first `N`
|
|
1068
|
-
//
|
|
1069
|
-
//
|
|
1070
|
-
//
|
|
1071
|
-
//
|
|
1072
|
-
//
|
|
1073
|
-
//
|
|
1104
|
+
// first `N` result rows before applying `limit`.
|
|
1105
|
+
//
|
|
1106
|
+
// **Consumed in ranked mode** (protocol v14+): on a request that
|
|
1107
|
+
// routes to the ranked executor (`group_by` + a single `order_by`
|
|
1108
|
+
// naming the selected aggregate), `offset` skips that many ranks
|
|
1109
|
+
// before the returned page, so `ORDER BY avg(grade) DESC LIMIT 1
|
|
1110
|
+
// OFFSET 4` is the 5th-best group. The skip is **count-attested**,
|
|
1111
|
+
// not walked: grovedb proves it from the counted subtree
|
|
1112
|
+
// commitments, so the proof stays `O(log n + k)` at any offset and
|
|
1113
|
+
// the response echoes the attested number in
|
|
1114
|
+
// `RankedEntries.skipped`. There is deliberately no ceiling — an
|
|
1115
|
+
// offset of 4 and an offset of four billion cost the same, so
|
|
1116
|
+
// there is no denial-of-service lever a cap would close. An offset
|
|
1117
|
+
// past the end of the ranking is a provable answer rather than an
|
|
1118
|
+
// error: `entries` comes back empty and `skipped` is the ranking's
|
|
1119
|
+
// whole population.
|
|
1120
|
+
//
|
|
1121
|
+
// **Rejected everywhere else** with
|
|
1122
|
+
// `Unsupported("OFFSET pagination is not yet implemented")` —
|
|
1123
|
+
// including on every path at protocol v13 and earlier, which has
|
|
1124
|
+
// no ranked executor. Cursor pagination via `start_after` /
|
|
1125
|
+
// `start_at` remains the supported way to page through documents.
|
|
1074
1126
|
optional uint32 offset = 12;
|
|
1075
1127
|
}
|
|
1076
1128
|
|
|
@@ -1258,9 +1310,115 @@ message GetDocumentsResponse {
|
|
|
1258
1310
|
}
|
|
1259
1311
|
}
|
|
1260
1312
|
|
|
1313
|
+
// One group in a ranked (`GROUP BY … ORDER BY <agg> LIMIT n`)
|
|
1314
|
+
// result: the group's index key plus the aggregate it was ranked
|
|
1315
|
+
// by.
|
|
1316
|
+
//
|
|
1317
|
+
// `key` is the raw index-key bytes of the GROUP BY property's
|
|
1318
|
+
// value — the same bytes that name the group's value tree under
|
|
1319
|
+
// the index (for a `string` property, its UTF-8 bytes). Clients
|
|
1320
|
+
// that want the typed value decode it with the document type's
|
|
1321
|
+
// key deserialization; the wire carries bytes so prover and
|
|
1322
|
+
// verifier agree without a schema round-trip.
|
|
1323
|
+
//
|
|
1324
|
+
// Exactly one `value` variant is set, determined by the
|
|
1325
|
+
// request's SELECT function:
|
|
1326
|
+
// * `count` — `SELECT COUNT(*)`, ranked on the index's
|
|
1327
|
+
// `rankedCountable` axis.
|
|
1328
|
+
// * `sum` — `SELECT SUM(field)`, `rankedSummable` axis.
|
|
1329
|
+
// Signed for the same reason `SumEntry.sum` is.
|
|
1330
|
+
// * `avg` — `SELECT AVG(field)`,
|
|
1331
|
+
// `rankedAverageable` axis.
|
|
1332
|
+
message RankedEntry {
|
|
1333
|
+
bytes key = 1;
|
|
1334
|
+
oneof value {
|
|
1335
|
+
// `jstype = JS_STRING` so JS/Web clients receive a string
|
|
1336
|
+
// and don't round counts > 2^53−1 to the nearest
|
|
1337
|
+
// representable Number — same choice as `CountEntry.count`.
|
|
1338
|
+
uint64 count = 2 [jstype = JS_STRING];
|
|
1339
|
+
// `jstype = JS_STRING` for the same precision reason as
|
|
1340
|
+
// `SumEntry.sum`.
|
|
1341
|
+
sint64 sum = 3 [jstype = JS_STRING];
|
|
1342
|
+
// The group's average, as a **`double` approximation** of the
|
|
1343
|
+
// exact value the Avg axis is ordered by.
|
|
1344
|
+
//
|
|
1345
|
+
// What grovedb actually commits to and sorts by is an `i128`
|
|
1346
|
+
// fixed-point integer: `floor(sum * SCALE / count)` with
|
|
1347
|
+
// euclidean (toward −∞) division, where SCALE is grovedb's
|
|
1348
|
+
// `AVG_FIXED_POINT_SCALE` (currently 10^19). This field is
|
|
1349
|
+
// that integer divided by SCALE in `f64`, i.e.
|
|
1350
|
+
// `fixed_point as f64 / SCALE as f64`.
|
|
1351
|
+
//
|
|
1352
|
+
// A `double` is honest here because `RankedEntry` is only ever
|
|
1353
|
+
// populated on the **no-proof ("quick answer") path**, where
|
|
1354
|
+
// the client has already chosen to trust the server's reply.
|
|
1355
|
+
// A proof-verifying client never reads this field: it
|
|
1356
|
+
// reconstructs each entry from the grovedb proof itself, where
|
|
1357
|
+
// the exact fixed-point `i128` lives, so nothing about proof
|
|
1358
|
+
// verification depends on this number's precision.
|
|
1359
|
+
//
|
|
1360
|
+
// Precision bound: `f64` carries ~15–16 significant decimal
|
|
1361
|
+
// digits, so two groups whose exact fixed-point averages differ
|
|
1362
|
+
// only beyond that can compare equal here. Do not use this
|
|
1363
|
+
// value for equality checks, tie-breaking, or any
|
|
1364
|
+
// reconstruction of the committed integer — request the proof
|
|
1365
|
+
// and read the fixed point from it instead. Entry *order* is
|
|
1366
|
+
// still exact: the server ranks on the i128 before converting.
|
|
1367
|
+
//
|
|
1368
|
+
// SCALE is a grovedb constant, not a wire constant: it moved
|
|
1369
|
+
// from 10^15 to 10^19 before release. Clients that need it
|
|
1370
|
+
// (e.g. to go back to fixed point on the proof path) should
|
|
1371
|
+
// read it from the SDK's re-export (`RANKED_AVG_SCALE`) rather
|
|
1372
|
+
// than hardcoding the literal.
|
|
1373
|
+
double avg = 4;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
// Ranked result entries. **Entry order IS the ranking order** —
|
|
1378
|
+
// best-first for `ORDER BY <agg> DESC`, worst-first for `ASC`.
|
|
1379
|
+
// Clients must not re-sort; ties (equal aggregates) come back in
|
|
1380
|
+
// group-key order in the direction of the walk, which is
|
|
1381
|
+
// descending group-key order for `DESC`.
|
|
1382
|
+
//
|
|
1383
|
+
// Fewer than `limit` entries is normal — the index simply has
|
|
1384
|
+
// fewer groups than requested — and is not an error.
|
|
1385
|
+
message RankedEntries {
|
|
1386
|
+
repeated RankedEntry entries = 1;
|
|
1387
|
+
|
|
1388
|
+
// How many groups were skipped before the first entry — the
|
|
1389
|
+
// page's **starting rank base**. Entry `i` of `entries` is the
|
|
1390
|
+
// group at rank `skipped + i` (0-based).
|
|
1391
|
+
//
|
|
1392
|
+
// `0` for an `OFFSET 0` (or offset-less) query, which is what
|
|
1393
|
+
// makes this field additive: a caller that never paginates sees
|
|
1394
|
+
// the value it would have assumed. For `OFFSET m` it is
|
|
1395
|
+
// normally `m`, and it is what turns a page back into a
|
|
1396
|
+
// *ranking* — without it, a caller who asked for
|
|
1397
|
+
// `ORDER BY avg(grade) DESC LIMIT 1 OFFSET 4` receives one
|
|
1398
|
+
// entry with no way to tell that it really is the 5th-best
|
|
1399
|
+
// group rather than the best.
|
|
1400
|
+
//
|
|
1401
|
+
// **When a requested offset exceeds the population**, `entries`
|
|
1402
|
+
// is empty and `skipped` is the ranking's attested *total*
|
|
1403
|
+
// population — a positive, useful answer ("there are only 12
|
|
1404
|
+
// groups") rather than a bare empty list.
|
|
1405
|
+
//
|
|
1406
|
+
// On the proved path the number is grovedb's cryptographically
|
|
1407
|
+
// attested count, re-derived by the verifier from the counted
|
|
1408
|
+
// subtree commitments in the proof bytes rather than trusted
|
|
1409
|
+
// from this field; a proving client should use the verified
|
|
1410
|
+
// value. On the unproven read there is nothing to attest and
|
|
1411
|
+
// grovedb's read API does not report a short walk, so the server
|
|
1412
|
+
// echoes the requested offset. The two therefore disagree in
|
|
1413
|
+
// exactly one case — an offset past the end, where the unproven
|
|
1414
|
+
// read reports the request and the proved one reports the truth.
|
|
1415
|
+
// Callers who need the population must prove.
|
|
1416
|
+
optional uint64 skipped = 2 [jstype = JS_STRING];
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1261
1419
|
// Non-proof result wrapper. The outer `oneof result` switches
|
|
1262
1420
|
// between this and `proof`; this inner oneof switches between
|
|
1263
|
-
// the
|
|
1421
|
+
// the non-proof shapes the v1 surface can return.
|
|
1264
1422
|
message ResultData {
|
|
1265
1423
|
oneof variant {
|
|
1266
1424
|
Documents documents = 1;
|
|
@@ -1280,6 +1438,18 @@ message GetDocumentsResponse {
|
|
|
1280
1438
|
// `book/src/drive/average-index-examples.md` for the design
|
|
1281
1439
|
// and the grades-contract worked example.
|
|
1282
1440
|
AverageResults averages = 4;
|
|
1441
|
+
// Ranked-aggregate result. Routed when the request pairs a
|
|
1442
|
+
// single-property `group_by` with a single `order_by` clause
|
|
1443
|
+
// naming the single aggregate `select` (the `$count` sentinel
|
|
1444
|
+
// for `COUNT(*)`) and a `limit` — SQL's `ORDER BY <agg>
|
|
1445
|
+
// DESC LIMIT n [OFFSET m]`. Answered from the per-axis
|
|
1446
|
+
// secondary of an indexed tree, so the index must declare the
|
|
1447
|
+
// matching `rankedCountable` / `rankedSummable` /
|
|
1448
|
+
// `rankedAverageable` keyword (meta-schema v3, protocol
|
|
1449
|
+
// version 14+). Entry order is the ranking order, and
|
|
1450
|
+
// `skipped` carries the page's starting rank — see
|
|
1451
|
+
// `RankedEntries`.
|
|
1452
|
+
RankedEntries ranked = 5;
|
|
1283
1453
|
}
|
|
1284
1454
|
}
|
|
1285
1455
|
|