drive/query/drive_document_sum_query/executors/
total.rs1use super::super::index_picker::find_summable_index_for_where_clauses;
9use super::super::{DriveDocumentSumQuery, SumEntry};
10use crate::drive::Drive;
11use crate::error::query::QuerySyntaxError;
12use crate::error::Error;
13use crate::query::ResolvedTimeRange;
14use crate::query::WhereClause;
15use dpp::data_contract::document_type::DocumentTypeRef;
16use dpp::version::PlatformVersion;
17use grovedb::TransactionArg;
18
19impl Drive {
20 #[allow(clippy::too_many_arguments)]
28 pub fn execute_document_sum_total_no_proof(
29 &self,
30 contract_id: [u8; 32],
31 document_type: DocumentTypeRef,
32 document_type_name: String,
33 where_clauses: Vec<WhereClause>,
34 resolved_time_ranges: &[ResolvedTimeRange],
35 sum_property: String,
36 transaction: TransactionArg,
37 platform_version: &PlatformVersion,
38 ) -> Result<Vec<SumEntry>, Error> {
39 use dpp::data_contract::document_type::accessors::{
40 DocumentTypeV0Getters, DocumentTypeV2Getters,
41 };
42
43 if where_clauses.is_empty()
48 && document_type
49 .documents_summable()
50 .map(|p| p == sum_property)
51 .unwrap_or(false)
52 {
53 let sum = self.read_primary_key_sum_tree(
54 &contract_id,
55 &document_type_name,
56 transaction,
57 platform_version,
58 )?;
59 return Ok(vec![SumEntry {
60 in_key: None,
61 key: vec![],
62 sum: Some(sum),
63 }]);
64 }
65
66 let index = find_summable_index_for_where_clauses(
67 document_type.indexes(),
68 &where_clauses,
69 &sum_property,
70 resolved_time_ranges,
71 )
72 .ok_or_else(|| {
73 Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty(
74 "sum query requires a `summable: \"<prop>\"` index whose properties \
75 exactly match the where clause fields and whose summed property \
76 matches the request's `sum_property`, or `documentsSummable: \
77 \"<prop>\"` on the document type for unfiltered total sums"
78 .to_string(),
79 ))
80 })?;
81 let sum_query = DriveDocumentSumQuery {
82 document_type,
83 contract_id,
84 document_type_name,
85 index,
86 where_clauses,
87 sum_property,
88 };
89 sum_query.execute_no_proof(self, transaction, platform_version)
90 }
91
92 pub(super) fn read_primary_key_sum_tree(
104 &self,
105 contract_id: &[u8; 32],
106 document_type_name: &str,
107 transaction: TransactionArg,
108 platform_version: &PlatformVersion,
109 ) -> Result<i64, Error> {
110 let drive_version = &platform_version.drive;
111 let path = [
112 &[crate::drive::RootTree::DataContractDocuments as u8] as &[u8],
113 contract_id,
114 &[1u8],
115 document_type_name.as_bytes(),
116 ];
117 let mut drive_operations = vec![];
118 let element = self
119 .grove_get_raw_optional(
120 grovedb_path::SubtreePath::from(path.as_slice()),
121 &[0],
122 crate::util::grove_operations::DirectQueryType::StatefulDirectQuery,
123 transaction,
124 &mut drive_operations,
125 drive_version,
126 )?
127 .ok_or_else(|| {
128 Error::Drive(crate::error::drive::DriveError::CorruptedCodeExecution(
129 "missing primary-key sum tree for an applied document type — \
130 insert_contract_operations_v0 must have created it",
131 ))
132 })?;
133 Ok(element.sum_value_or_default())
134 }
135}