drive/query/drive_document_count_query/executors/
total.rs1use super::super::super::conditions::WhereClause;
5use super::super::{DriveDocumentCountQuery, SplitCountEntry};
6use crate::drive::Drive;
7use crate::error::query::QuerySyntaxError;
8use crate::error::Error;
9use crate::query::ResolvedTimeRange;
10use dpp::data_contract::document_type::DocumentTypeRef;
11use dpp::version::PlatformVersion;
12use grovedb::TransactionArg;
13
14impl Drive {
15 #[allow(clippy::too_many_arguments)]
23 pub fn execute_document_count_total_no_proof(
24 &self,
25 contract_id: [u8; 32],
26 document_type: DocumentTypeRef,
27 document_type_name: String,
28 where_clauses: Vec<WhereClause>,
29 resolved_time_ranges: &[ResolvedTimeRange],
30 transaction: TransactionArg,
31 platform_version: &PlatformVersion,
32 ) -> Result<Vec<SplitCountEntry>, Error> {
33 use dpp::data_contract::document_type::accessors::{
34 DocumentTypeV0Getters, DocumentTypeV2Getters,
35 };
36
37 if where_clauses.is_empty() && document_type.documents_countable() {
42 let count = self.read_primary_key_count_tree(
43 &contract_id,
44 &document_type_name,
45 transaction,
46 platform_version,
47 )?;
48 return Ok(vec![SplitCountEntry {
49 in_key: None,
50 key: vec![],
51 count: Some(count),
56 }]);
57 }
58
59 let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses(
60 document_type.indexes(),
61 &where_clauses,
62 resolved_time_ranges,
63 )
64 .ok_or_else(|| {
65 Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty(
66 "count query requires a `countable: true` index whose properties \
67 exactly match the where clause fields, a `rangeCountable: true` \
68 index they cover up to its last property, or \
69 `documentsCountable: true` on the document type for unfiltered \
70 total counts"
71 .to_string(),
72 ))
73 })?;
74 let count_query = DriveDocumentCountQuery {
75 document_type,
76 contract_id,
77 document_type_name,
78 index,
79 where_clauses,
80 };
81 count_query.execute_no_proof(self, transaction, platform_version)
82 }
83
84 pub(super) fn read_primary_key_count_tree(
96 &self,
97 contract_id: &[u8; 32],
98 document_type_name: &str,
99 transaction: TransactionArg,
100 platform_version: &PlatformVersion,
101 ) -> Result<u64, Error> {
102 let drive_version = &platform_version.drive;
103 let path = [
104 &[crate::drive::RootTree::DataContractDocuments as u8] as &[u8],
105 contract_id,
106 &[1u8],
107 document_type_name.as_bytes(),
108 ];
109 let mut drive_operations = vec![];
110 let element = self.grove_get_raw_optional(
111 grovedb_path::SubtreePath::from(path.as_slice()),
112 &[0],
113 crate::util::grove_operations::DirectQueryType::StatefulDirectQuery,
114 transaction,
115 &mut drive_operations,
116 drive_version,
117 )?;
118 Ok(element.map_or(0, |e| e.count_value_or_default()))
119 }
120}