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, or `documentsCountable: \
68 true` on the document type for unfiltered total counts"
69 .to_string(),
70 ))
71 })?;
72 let count_query = DriveDocumentCountQuery {
73 document_type,
74 contract_id,
75 document_type_name,
76 index,
77 where_clauses,
78 };
79 count_query.execute_no_proof(self, transaction, platform_version)
80 }
81
82 pub(super) fn read_primary_key_count_tree(
94 &self,
95 contract_id: &[u8; 32],
96 document_type_name: &str,
97 transaction: TransactionArg,
98 platform_version: &PlatformVersion,
99 ) -> Result<u64, Error> {
100 let drive_version = &platform_version.drive;
101 let path = [
102 &[crate::drive::RootTree::DataContractDocuments as u8] as &[u8],
103 contract_id,
104 &[1u8],
105 document_type_name.as_bytes(),
106 ];
107 let mut drive_operations = vec![];
108 let element = self.grove_get_raw_optional(
109 grovedb_path::SubtreePath::from(path.as_slice()),
110 &[0],
111 crate::util::grove_operations::DirectQueryType::StatefulDirectQuery,
112 transaction,
113 &mut drive_operations,
114 drive_version,
115 )?;
116 Ok(element.map_or(0, |e| e.count_value_or_default()))
117 }
118}