1use std::sync::Arc;
2
3#[cfg(any(feature = "server", feature = "verify"))]
4pub use {
5 conditions::{ValueClause, WhereClause, WhereOperator},
6 drive_document_count_query::{DocumentCountMode, DriveDocumentCountQuery, SplitCountEntry},
7 grovedb::{PathQuery, Query, QueryItem, SizedQuery},
8 ordering::OrderClause,
9 single_document_drive_query::SingleDocumentDriveQuery,
10 single_document_drive_query::SingleDocumentDriveQueryContestedStatus,
11 vote_polls_by_end_date_query::VotePollsByEndDateDriveQuery,
12 vote_query::IdentityBasedVoteDriveQuery,
13};
14
15#[cfg(feature = "server")]
16pub use drive_document_count_query::{
17 CountMode, DocumentCountRequest, DocumentCountResponse, RangeCountOptions,
18 MAX_LIMIT_AS_FAILSAFE,
19};
20#[cfg(any(feature = "server", feature = "verify"))]
22use {
23 crate::{
24 drive::contract::paths::DataContractPaths,
25 error::{drive::DriveError, query::QuerySyntaxError, Error},
26 },
27 dpp::{
28 data_contract::{
29 accessors::v0::DataContractV0Getters,
30 document_type::{accessors::DocumentTypeV0Getters, methods::DocumentTypeV0Methods},
31 document_type::{DocumentTypeRef, Index, IndexProperty},
32 DataContract,
33 },
34 document::{document_methods::DocumentMethodsV0, Document, DocumentV0Getters},
35 platform_value::{btreemap_extensions::BTreeValueRemoveFromMapHelper, Value},
36 version::PlatformVersion,
37 ProtocolError,
38 },
39 indexmap::IndexMap,
40 sqlparser::{
41 ast::{self, OrderByExpr, Select, Statement, TableFactor::Table, Value::Number},
42 dialect::MySqlDialect,
43 parser::Parser,
44 },
45 std::{collections::BTreeMap, ops::BitXor},
46};
47
48#[cfg(all(feature = "server", feature = "verify"))]
49use crate::verify::RootHash;
50
51#[cfg(feature = "server")]
52use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0;
53#[cfg(feature = "server")]
54pub use grovedb::{
55 query_result_type::{QueryResultElements, QueryResultType},
56 Element, Error as GroveError, TransactionArg,
57};
58
59use dpp::document;
60use dpp::prelude::Identifier;
61use dpp::validation::{SimpleValidationResult, ValidationResult};
62#[cfg(feature = "server")]
63use {
64 crate::{drive::Drive, fees::op::LowLevelDriveOperation},
65 dpp::block::block_info::BlockInfo,
66};
67use crate::config::DriveConfig;
69use crate::util::common::encode::encode_u64;
71#[cfg(feature = "server")]
72use crate::util::grove_operations::QueryType::StatefulQuery;
73
74#[cfg(any(feature = "server", feature = "verify"))]
76pub mod conditions;
77#[cfg(any(feature = "server", feature = "verify"))]
78mod defaults;
79#[cfg(any(feature = "server", feature = "verify"))]
80pub mod ordering;
81#[cfg(any(feature = "server", feature = "verify"))]
82mod single_document_drive_query;
83
84#[cfg(feature = "server")]
86mod test_index;
87
88#[cfg(any(feature = "server", feature = "verify"))]
89pub mod vote_poll_vote_state_query;
91#[cfg(any(feature = "server", feature = "verify"))]
92pub mod vote_query;
94
95#[cfg(any(feature = "server", feature = "verify"))]
96pub mod vote_poll_contestant_votes_query;
98
99#[cfg(any(feature = "server", feature = "verify"))]
100pub mod vote_polls_by_end_date_query;
102
103#[cfg(any(feature = "server", feature = "verify"))]
104pub mod vote_polls_by_document_type_query;
106
107#[cfg(any(feature = "server", feature = "verify"))]
113pub type ContractLookupFn<'a> =
114 dyn Fn(&Identifier) -> Result<Option<Arc<DataContract>>, Error> + 'a;
115
116#[cfg(any(feature = "server", feature = "verify"))]
127pub fn contract_lookup_fn_for_contract<'a>(
128 data_contract: Arc<DataContract>,
129) -> Box<ContractLookupFn<'a>> {
130 let func = move |id: &Identifier| -> Result<Option<Arc<DataContract>>, Error> {
131 if data_contract.id().ne(id) {
132 return Ok(None);
133 }
134 Ok(Some(Arc::clone(&data_contract)))
135 };
136 Box::new(func)
137}
138
139#[cfg(any(feature = "server", feature = "verify"))]
141pub mod contested_resource_votes_given_by_identity_query;
142#[cfg(any(feature = "server", feature = "verify"))]
144pub mod drive_contested_document_query;
145
146#[cfg(any(feature = "server", feature = "verify"))]
148pub mod proposer_block_count_query;
149
150#[cfg(any(feature = "server", feature = "verify"))]
152pub mod identity_token_balance_drive_query;
153#[cfg(any(feature = "server", feature = "verify"))]
155pub mod identity_token_info_drive_query;
156
157#[cfg(any(feature = "server", feature = "verify"))]
159pub mod filter;
160#[cfg(any(feature = "server", feature = "verify"))]
162pub mod token_status_drive_query;
163
164#[cfg(any(feature = "server", feature = "verify"))]
166pub mod drive_document_count_query;
167
168pub type QuerySyntaxValidationResult<TData> = ValidationResult<TData, QuerySyntaxError>;
170
171pub type QuerySyntaxSimpleValidationResult = SimpleValidationResult<QuerySyntaxError>;
173
174#[cfg(any(feature = "server", feature = "verify"))]
175#[derive(Debug, Clone)]
182pub struct StartAtDocument<'a> {
183 pub document: Document,
185
186 pub document_type: DocumentTypeRef<'a>,
188
189 pub included: bool,
193}
194
195#[cfg(any(feature = "server", feature = "verify"))]
197#[derive(Clone, Debug, PartialEq, Default)]
198pub struct InternalClauses {
199 pub primary_key_in_clause: Option<WhereClause>,
201 pub primary_key_equal_clause: Option<WhereClause>,
203 pub in_clause: Option<WhereClause>,
205 pub range_clause: Option<WhereClause>,
207 pub equal_clauses: BTreeMap<String, WhereClause>,
209}
210
211impl InternalClauses {
212 #[cfg(any(feature = "server", feature = "verify"))]
213 pub fn verify(&self) -> bool {
215 if self
217 .primary_key_in_clause
218 .is_some()
219 .bitxor(self.primary_key_equal_clause.is_some())
220 {
221 !(self.in_clause.is_some()
223 || self.range_clause.is_some()
224 || !self.equal_clauses.is_empty())
225 } else {
226 !(self.primary_key_in_clause.is_some() && self.primary_key_equal_clause.is_some())
227 }
228 }
229
230 #[cfg(any(feature = "server", feature = "verify"))]
231 pub fn is_for_primary_key(&self) -> bool {
233 self.primary_key_in_clause.is_some() || self.primary_key_equal_clause.is_some()
234 }
235
236 #[cfg(any(feature = "server", feature = "verify"))]
237 pub fn is_empty(&self) -> bool {
239 self.in_clause.is_none()
240 && self.range_clause.is_none()
241 && self.equal_clauses.is_empty()
242 && self.primary_key_in_clause.is_none()
243 && self.primary_key_equal_clause.is_none()
244 }
245
246 #[cfg(any(feature = "server", feature = "verify"))]
247 pub fn extract_from_clauses(all_where_clauses: Vec<WhereClause>) -> Result<Self, Error> {
249 let primary_key_equal_clauses_array = all_where_clauses
250 .iter()
251 .filter_map(|where_clause| match where_clause.operator {
252 WhereOperator::Equal => match where_clause.is_identifier() {
253 true => Some(where_clause.clone()),
254 false => None,
255 },
256 _ => None,
257 })
258 .collect::<Vec<WhereClause>>();
259
260 let primary_key_in_clauses_array = all_where_clauses
261 .iter()
262 .filter_map(|where_clause| match where_clause.operator {
263 WhereOperator::In => match where_clause.is_identifier() {
264 true => Some(where_clause.clone()),
265 false => None,
266 },
267 _ => None,
268 })
269 .collect::<Vec<WhereClause>>();
270
271 let (equal_clauses, range_clause, in_clause) =
272 WhereClause::group_clauses(&all_where_clauses)?;
273
274 let primary_key_equal_clause = match primary_key_equal_clauses_array.len() {
275 0 => Ok(None),
276 1 => Ok(Some(
277 primary_key_equal_clauses_array
278 .first()
279 .expect("there must be a value")
280 .clone(),
281 )),
282 _ => Err(Error::Query(
283 QuerySyntaxError::DuplicateNonGroupableClauseSameField(
284 "There should only be one equal clause for the primary key",
285 ),
286 )),
287 }?;
288
289 let primary_key_in_clause = match primary_key_in_clauses_array.len() {
290 0 => Ok(None),
291 1 => Ok(Some(
292 primary_key_in_clauses_array
293 .first()
294 .expect("there must be a value")
295 .clone(),
296 )),
297 _ => Err(Error::Query(
298 QuerySyntaxError::DuplicateNonGroupableClauseSameField(
299 "There should only be one in clause for the primary key",
300 ),
301 )),
302 }?;
303
304 let internal_clauses = InternalClauses {
305 primary_key_equal_clause,
306 primary_key_in_clause,
307 in_clause,
308 range_clause,
309 equal_clauses,
310 };
311
312 match internal_clauses.verify() {
313 true => Ok(internal_clauses),
314 false => Err(Error::Query(
315 QuerySyntaxError::InvalidWhereClauseComponents("Query has invalid where clauses"),
316 )),
317 }
318 }
319
320 #[cfg(any(feature = "server", feature = "verify"))]
322 pub fn validate_against_schema(
323 &self,
324 document_type: DocumentTypeRef,
325 ) -> QuerySyntaxSimpleValidationResult {
326 if !self.verify() {
328 return QuerySyntaxSimpleValidationResult::new_with_error(
329 QuerySyntaxError::InvalidWhereClauseComponents(
330 "invalid composition of where clauses",
331 ),
332 );
333 }
334
335 if let Some(in_clause) = &self.in_clause {
337 if in_clause.field == "$id" {
339 return QuerySyntaxSimpleValidationResult::new_with_error(
340 QuerySyntaxError::InvalidWhereClauseComponents(
341 "use primary_key_* clauses for $id",
342 ),
343 );
344 }
345 let result = in_clause.validate_against_schema(document_type);
346 if !result.is_valid() {
347 return result;
348 }
349 }
350
351 if let Some(range_clause) = &self.range_clause {
353 if range_clause.field == "$id" {
355 return QuerySyntaxSimpleValidationResult::new_with_error(
356 QuerySyntaxError::InvalidWhereClauseComponents(
357 "use primary_key_* clauses for $id",
358 ),
359 );
360 }
361 let result = range_clause.validate_against_schema(document_type);
362 if !result.is_valid() {
363 return result;
364 }
365 }
366
367 for (field, eq_clause) in &self.equal_clauses {
369 if field.as_str() == "$id" {
371 return QuerySyntaxSimpleValidationResult::new_with_error(
372 QuerySyntaxError::InvalidWhereClauseComponents(
373 "use primary_key_* clauses for $id",
374 ),
375 );
376 }
377 let result = eq_clause.validate_against_schema(document_type);
378 if !result.is_valid() {
379 return result;
380 }
381 }
382
383 if let Some(pk_eq) = &self.primary_key_equal_clause {
385 if pk_eq.operator != WhereOperator::Equal
386 || !matches!(pk_eq.value, Value::Identifier(_))
387 {
388 return QuerySyntaxSimpleValidationResult::new_with_error(
389 QuerySyntaxError::InvalidWhereClauseComponents(
390 "primary key equality must compare an identifier",
391 ),
392 );
393 }
394 }
395 if let Some(pk_in) = &self.primary_key_in_clause {
396 if pk_in.operator != WhereOperator::In {
397 return QuerySyntaxSimpleValidationResult::new_with_error(
398 QuerySyntaxError::InvalidWhereClauseComponents(
399 "primary key IN must use IN operator",
400 ),
401 );
402 }
403 let result = pk_in.in_values();
405 if !result.is_valid() {
406 return QuerySyntaxSimpleValidationResult::new_with_errors(result.errors);
407 }
408 if let Value::Array(arr) = &pk_in.value {
409 if !arr.iter().all(|v| matches!(v, Value::Identifier(_))) {
410 return QuerySyntaxSimpleValidationResult::new_with_error(
411 QuerySyntaxError::InvalidWhereClauseComponents(
412 "primary key IN must contain identifiers",
413 ),
414 );
415 }
416 } else {
417 return QuerySyntaxSimpleValidationResult::new_with_error(
418 QuerySyntaxError::InvalidWhereClauseComponents(
419 "primary key IN must contain an array of identifiers",
420 ),
421 );
422 }
423 }
424
425 QuerySyntaxSimpleValidationResult::default()
426 }
427}
428
429impl From<InternalClauses> for Vec<WhereClause> {
430 fn from(clauses: InternalClauses) -> Self {
431 let mut result: Self = clauses.equal_clauses.into_values().collect();
432
433 if let Some(clause) = clauses.in_clause {
434 result.push(clause);
435 };
436 if let Some(clause) = clauses.primary_key_equal_clause {
437 result.push(clause);
438 };
439 if let Some(clause) = clauses.primary_key_in_clause {
440 result.push(clause);
441 };
442 if let Some(clause) = clauses.range_clause {
443 result.push(clause);
444 };
445
446 result
447 }
448}
449
450#[cfg(any(feature = "server", feature = "verify"))]
451#[derive(Debug, PartialEq, Clone)]
453pub struct DriveDocumentQuery<'a> {
454 pub contract: &'a DataContract,
456 pub document_type: DocumentTypeRef<'a>,
458 pub internal_clauses: InternalClauses,
460 pub offset: Option<u16>,
462 pub limit: Option<u16>,
464 pub order_by: IndexMap<String, OrderClause>,
466 pub start_at: Option<[u8; 32]>,
468 pub start_at_included: bool,
470 pub block_time_ms: Option<u64>,
472}
473
474impl<'a> DriveDocumentQuery<'a> {
475 #[cfg(any(feature = "server", feature = "verify"))]
477 pub fn new_primary_key_single_item_query(
478 contract: &'a DataContract,
479 document_type: DocumentTypeRef<'a>,
480 id: Identifier,
481 ) -> Self {
482 DriveDocumentQuery {
483 contract,
484 document_type,
485 internal_clauses: InternalClauses {
486 primary_key_in_clause: None,
487 primary_key_equal_clause: Some(WhereClause {
488 field: document::property_names::ID.to_string(),
489 operator: WhereOperator::Equal,
490 value: Value::Identifier(id.to_buffer()),
491 }),
492 in_clause: None,
493 range_clause: None,
494 equal_clauses: Default::default(),
495 },
496 offset: None,
497 limit: None,
498 order_by: Default::default(),
499 start_at: None,
500 start_at_included: false,
501 block_time_ms: None,
502 }
503 }
504
505 #[cfg(feature = "server")]
506 pub fn any_item_query(contract: &'a DataContract, document_type: DocumentTypeRef<'a>) -> Self {
508 DriveDocumentQuery {
509 contract,
510 document_type,
511 internal_clauses: Default::default(),
512 offset: None,
513 limit: Some(1),
514 order_by: Default::default(),
515 start_at: None,
516 start_at_included: true,
517 block_time_ms: None,
518 }
519 }
520
521 #[cfg(feature = "server")]
522 pub fn all_items_query(
524 contract: &'a DataContract,
525 document_type: DocumentTypeRef<'a>,
526 limit: Option<u16>,
527 ) -> Self {
528 DriveDocumentQuery {
529 contract,
530 document_type,
531 internal_clauses: Default::default(),
532 offset: None,
533 limit,
534 order_by: Default::default(),
535 start_at: None,
536 start_at_included: true,
537 block_time_ms: None,
538 }
539 }
540
541 #[cfg(any(feature = "server", feature = "verify"))]
542 pub fn is_for_primary_key(&self) -> bool {
544 self.internal_clauses.is_for_primary_key()
545 || (self.internal_clauses.is_empty()
546 && (self.order_by.is_empty()
547 || (self.order_by.len() == 1
548 && self
549 .order_by
550 .keys()
551 .collect::<Vec<&String>>()
552 .first()
553 .unwrap()
554 .as_str()
555 == "$id")))
556 }
557
558 #[cfg(feature = "cbor_query")]
559 pub fn from_cbor(
561 query_cbor: &[u8],
562 contract: &'a DataContract,
563 document_type: DocumentTypeRef<'a>,
564 config: &DriveConfig,
565 ) -> Result<Self, Error> {
566 let query_document_value: Value = ciborium::de::from_reader(query_cbor).map_err(|_| {
567 Error::Query(QuerySyntaxError::DeserializationError(
568 "unable to decode query from cbor".to_string(),
569 ))
570 })?;
571 Self::from_value(query_document_value, contract, document_type, config)
572 }
573
574 #[cfg(any(feature = "server", feature = "verify"))]
575 pub fn from_value(
577 query_value: Value,
578 contract: &'a DataContract,
579 document_type: DocumentTypeRef<'a>,
580 config: &DriveConfig,
581 ) -> Result<Self, Error> {
582 let query_document: BTreeMap<String, Value> = query_value.into_btree_string_map()?;
583 Self::from_btree_map_value(query_document, contract, document_type, config)
584 }
585
586 #[cfg(any(feature = "server", feature = "verify"))]
587 pub fn from_btree_map_value(
589 mut query_document: BTreeMap<String, Value>,
590 contract: &'a DataContract,
591 document_type: DocumentTypeRef<'a>,
592 config: &DriveConfig,
593 ) -> Result<Self, Error> {
594 if let Some(contract_id) = query_document
595 .remove_optional_identifier("contract_id")
596 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?
597 {
598 if contract.id() != contract_id {
599 return Err(ProtocolError::IdentifierError(format!(
600 "data contract id mismatch, expected: {}, got: {}",
601 contract.id(),
602 contract_id
603 ))
604 .into());
605 };
606 }
607
608 if let Some(document_type_name) = query_document
609 .remove_optional_string("document_type_name")
610 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?
611 {
612 if document_type.name() != &document_type_name {
613 return Err(ProtocolError::IdentifierError(format!(
614 "document type name mismatch, expected: {}, got: {}",
615 document_type.name(),
616 document_type_name
617 ))
618 .into());
619 }
620 }
621
622 let maybe_limit: Option<u16> = query_document
623 .remove_optional_integer("limit")
624 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?;
625
626 let limit = maybe_limit
627 .map_or(Some(config.default_query_limit), |limit_value| {
628 if limit_value == 0 || limit_value > config.default_query_limit {
629 None
630 } else {
631 Some(limit_value)
632 }
633 })
634 .ok_or(Error::Query(QuerySyntaxError::InvalidLimit(format!(
635 "limit greater than max limit {}",
636 config.max_query_limit
637 ))))?;
638
639 let offset: Option<u16> = query_document
640 .remove_optional_integer("offset")
641 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?;
642
643 let block_time_ms: Option<u64> = query_document
644 .remove_optional_integer("blockTime")
645 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?;
646
647 let all_where_clauses: Vec<WhereClause> =
648 query_document
649 .remove("where")
650 .map_or(Ok(vec![]), |id_cbor| {
651 if let Value::Array(clauses) = id_cbor {
652 clauses
653 .iter()
654 .map(|where_clause| {
655 if let Value::Array(clauses_components) = where_clause {
656 WhereClause::from_components(clauses_components)
657 } else {
658 Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause(
659 "where clause must be an array".to_string(),
660 )))
661 }
662 })
663 .collect::<Result<Vec<WhereClause>, Error>>()
664 } else {
665 Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause(
666 "where clause must be an array".to_string(),
667 )))
668 }
669 })?;
670
671 let internal_clauses = InternalClauses::extract_from_clauses(all_where_clauses)?;
672
673 let start_at_option = query_document.remove("startAt");
674 let start_after_option = query_document.remove("startAfter");
675 if start_after_option.is_some() && start_at_option.is_some() {
676 return Err(Error::Query(QuerySyntaxError::DuplicateStartConditions(
677 "only one of startAt or startAfter should be provided",
678 )));
679 }
680
681 let mut start_at_included = true;
682
683 let mut start_option: Option<Value> = None;
684
685 if start_after_option.is_some() {
686 start_option = start_after_option;
687 start_at_included = false;
688 } else if start_at_option.is_some() {
689 start_option = start_at_option;
690 start_at_included = true;
691 }
692
693 let start_at: Option<[u8; 32]> = start_option
694 .map(|v| {
695 v.into_identifier()
696 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))
697 .map(|identifier| identifier.into_buffer())
698 })
699 .transpose()?;
700
701 let order_by: IndexMap<String, OrderClause> =
702 query_document
703 .remove("orderBy")
704 .map_or(Ok(IndexMap::new()), |id_cbor| {
705 if let Value::Array(clauses) = id_cbor {
706 clauses
707 .into_iter()
708 .filter_map(|order_clause| {
709 if let Value::Array(clauses_components) = order_clause {
710 let order_clause =
711 OrderClause::from_components(&clauses_components)
712 .map_err(Error::from);
713 match order_clause {
714 Ok(order_clause) => {
715 Some(Ok((order_clause.field.clone(), order_clause)))
716 }
717 Err(err) => Some(Err(err)),
718 }
719 } else {
720 None
721 }
722 })
723 .collect::<Result<IndexMap<String, OrderClause>, Error>>()
724 } else {
725 Err(Error::Query(QuerySyntaxError::InvalidOrderByProperties(
726 "order clauses must be an array",
727 )))
728 }
729 })?;
730
731 if !query_document.is_empty() {
732 return Err(Error::Query(QuerySyntaxError::Unsupported(format!(
733 "unsupported syntax in where clause: {:?}",
734 query_document
735 ))));
736 }
737
738 Ok(DriveDocumentQuery {
739 contract,
740 document_type,
741 internal_clauses,
742 limit: Some(limit),
743 offset,
744 order_by,
745 start_at,
746 start_at_included,
747 block_time_ms,
748 })
749 }
750
751 #[cfg(any(feature = "server", feature = "verify"))]
752 #[allow(clippy::too_many_arguments)]
754 pub fn from_decomposed_values(
755 where_clause: Value,
756 order_by: Option<Value>,
757 maybe_limit: Option<u16>,
758 start_at: Option<[u8; 32]>,
759 start_at_included: bool,
760 block_time_ms: Option<u64>,
761 contract: &'a DataContract,
762 document_type: DocumentTypeRef<'a>,
763 config: &DriveConfig,
764 ) -> Result<Self, Error> {
765 let limit = maybe_limit
766 .map_or(Some(config.default_query_limit), |limit_value| {
767 if limit_value == 0 || limit_value > config.default_query_limit {
768 None
769 } else {
770 Some(limit_value)
771 }
772 })
773 .ok_or(Error::Query(QuerySyntaxError::InvalidLimit(format!(
774 "limit greater than max limit {}",
775 config.max_query_limit
776 ))))?;
777
778 let all_where_clauses: Vec<WhereClause> = match where_clause {
779 Value::Null => Ok(vec![]),
780 Value::Array(clauses) => clauses
781 .iter()
782 .map(|where_clause| {
783 if let Value::Array(clauses_components) = where_clause {
784 WhereClause::from_components(clauses_components)
785 } else {
786 Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause(
787 "where clause must be an array".to_string(),
788 )))
789 }
790 })
791 .collect::<Result<Vec<WhereClause>, Error>>(),
792 _ => Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause(
793 "where clause must be an array".to_string(),
794 ))),
795 }?;
796
797 let internal_clauses = InternalClauses::extract_from_clauses(all_where_clauses)?;
798
799 let order_by: IndexMap<String, OrderClause> = order_by
800 .map_or(vec![], |id_cbor| {
801 if let Value::Array(clauses) = id_cbor {
802 clauses
803 .iter()
804 .filter_map(|order_clause| {
805 if let Value::Array(clauses_components) = order_clause {
806 OrderClause::from_components(clauses_components).ok()
807 } else {
808 None
809 }
810 })
811 .collect()
812 } else {
813 vec![]
814 }
815 })
816 .iter()
817 .map(|order_clause| Ok((order_clause.field.clone(), order_clause.to_owned())))
818 .collect::<Result<IndexMap<String, OrderClause>, Error>>()?;
819
820 Ok(DriveDocumentQuery {
821 contract,
822 document_type,
823 internal_clauses,
824 offset: None,
825 limit: Some(limit),
826 order_by,
827 start_at,
828 start_at_included,
829 block_time_ms,
830 })
831 }
832
833 #[cfg(any(feature = "server", feature = "verify"))]
834 pub fn from_sql_expr(
836 sql_string: &str,
837 contract: &'a DataContract,
838 config: Option<&DriveConfig>,
839 ) -> Result<Self, Error> {
840 let dialect: MySqlDialect = MySqlDialect {};
841 let statements: Vec<Statement> = Parser::parse_sql(&dialect, sql_string)
842 .map_err(|e| Error::Query(QuerySyntaxError::SQLParsingError(e)))?;
843
844 let first_statement =
846 statements
847 .first()
848 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
849 "Issue parsing sql getting first statement".to_string(),
850 )))?;
851
852 let query: &ast::Query = match first_statement {
853 ast::Statement::Query(query_struct) => Some(query_struct),
854 _ => None,
855 }
856 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
857 "Issue parsing sql: not a query".to_string(),
858 )))?;
859
860 let max_limit = config
861 .map(|config| config.max_query_limit)
862 .unwrap_or(DriveConfig::default().max_query_limit);
863
864 let limit: u16 = if let Some(limit_expr) = &query.limit {
865 match limit_expr {
866 ast::Expr::Value(Number(num_string, _)) => {
867 let cast_num_string: &String = num_string;
868 let user_limit = cast_num_string.parse::<u16>().map_err(|e| {
869 Error::Query(QuerySyntaxError::InvalidLimit(format!(
870 "limit could not be parsed {}",
871 e
872 )))
873 })?;
874 if user_limit > max_limit {
875 return Err(Error::Query(QuerySyntaxError::InvalidLimit(format!(
876 "limit {} greater than max limit {}",
877 user_limit, max_limit
878 ))));
879 }
880 user_limit
881 }
882 result => {
883 return Err(Error::Query(QuerySyntaxError::InvalidLimit(format!(
884 "expression not a limit {}",
885 result
886 ))));
887 }
888 }
889 } else {
890 config
891 .map(|config| config.default_query_limit)
892 .unwrap_or(DriveConfig::default().default_query_limit)
893 };
894
895 let order_by: IndexMap<String, OrderClause> = query
896 .order_by
897 .iter()
898 .map(|order_exp: &OrderByExpr| {
899 let ascending = order_exp.asc.is_none() || order_exp.asc.unwrap();
900 let field = order_exp.expr.to_string();
901 (field.clone(), OrderClause { field, ascending })
902 })
903 .collect::<IndexMap<String, OrderClause>>();
904
905 let select: &Select = match &*query.body {
907 ast::SetExpr::Select(select) => Some(select),
908 _ => None,
909 }
910 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
911 "Issue parsing sql: Not a select".to_string(),
912 )))?;
913
914 let document_type_name = match &select
916 .from
917 .first()
918 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
919 "Invalid query: missing from section".to_string(),
920 )))?
921 .relation
922 {
923 Table { name, .. } => name.0.first().as_ref().map(|identifier| &identifier.value),
924 _ => None,
925 }
926 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
927 "Issue parsing sql: invalid from value".to_string(),
928 )))?;
929
930 let document_type =
931 contract
932 .document_types()
933 .get(document_type_name)
934 .ok_or(Error::Query(QuerySyntaxError::DocumentTypeNotFound(
935 "document type not found in contract",
936 )))?;
937
938 let mut all_where_clauses: Vec<WhereClause> = Vec::new();
948 let selection_tree = select.selection.as_ref();
949
950 if let Some(selection_tree) = selection_tree {
952 WhereClause::build_where_clauses_from_operations(
953 selection_tree,
954 document_type,
955 &mut all_where_clauses,
956 )?;
957 }
958
959 let internal_clauses = InternalClauses::extract_from_clauses(all_where_clauses)?;
960
961 let start_at_option = None; let start_after_option = None; let mut start_at_included = true;
964 let mut start_option: Option<Value> = None;
965
966 if start_after_option.is_some() {
967 start_option = start_after_option;
968 start_at_included = false;
969 } else if start_at_option.is_some() {
970 start_option = start_at_option;
971 start_at_included = true;
972 }
973
974 let start_at: Option<[u8; 32]> = start_option
975 .map(|v| {
976 v.into_identifier()
977 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))
978 .map(|identifier| identifier.into_buffer())
979 })
980 .transpose()?;
981
982 Ok(DriveDocumentQuery {
983 contract,
984 document_type: document_type.as_ref(),
985 internal_clauses,
986 offset: None,
987 limit: Some(limit),
988 order_by,
989 start_at,
990 start_at_included,
991 block_time_ms: None,
992 })
993 }
994
995 #[cfg(feature = "cbor_query")]
1000 pub fn to_cbor(&self) -> Result<Vec<u8>, Error> {
1001 let data: BTreeMap<String, Value> = self.into();
1002 let cbor: BTreeMap<String, ciborium::Value> = Value::convert_to_cbor_map(data)?;
1003 let mut output = Vec::new();
1004
1005 ciborium::ser::into_writer(&cbor, &mut output)
1006 .map_err(|e| ProtocolError::PlatformSerializationError(e.to_string()))?;
1007 Ok(output)
1008 }
1009
1010 #[cfg(any(feature = "server", feature = "verify"))]
1011 pub fn start_at_document_path_and_key(&self, starts_at: &[u8; 32]) -> (Vec<Vec<u8>>, Vec<u8>) {
1013 if self.document_type.documents_keep_history() {
1014 let document_holding_path = self.contract.documents_with_history_primary_key_path(
1015 self.document_type.name().as_str(),
1016 starts_at,
1017 );
1018 (
1019 document_holding_path
1020 .into_iter()
1021 .map(|key| key.to_vec())
1022 .collect::<Vec<_>>(),
1023 vec![0],
1024 )
1025 } else {
1026 let document_holding_path = self
1027 .contract
1028 .documents_primary_key_path(self.document_type.name().as_str());
1029 (
1030 document_holding_path
1031 .into_iter()
1032 .map(|key| key.to_vec())
1033 .collect::<Vec<_>>(),
1034 starts_at.to_vec(),
1035 )
1036 }
1037 }
1038
1039 #[cfg(feature = "server")]
1040 pub fn construct_path_query_operations(
1042 &self,
1043 drive: &Drive,
1044 include_start_at_for_proof: bool,
1045 transaction: TransactionArg,
1046 drive_operations: &mut Vec<LowLevelDriveOperation>,
1047 platform_version: &PlatformVersion,
1048 ) -> Result<PathQuery, Error> {
1049 let drive_version = &platform_version.drive;
1050 let document_type_path = self
1052 .contract
1053 .document_type_path(self.document_type.name().as_str())
1054 .into_iter()
1055 .map(|a| a.to_vec())
1056 .collect::<Vec<Vec<u8>>>();
1057
1058 let (starts_at_document, start_at_path_query) = match &self.start_at {
1059 None => Ok((None, None)),
1060 Some(starts_at) => {
1061 let (start_at_document_path, start_at_document_key) =
1065 self.start_at_document_path_and_key(starts_at);
1066 let start_at_document = drive
1067 .grove_get(
1068 start_at_document_path.as_slice().into(),
1069 &start_at_document_key,
1070 StatefulQuery,
1071 transaction,
1072 drive_operations,
1073 drive_version,
1074 )
1075 .map_err(|e| match e {
1076 Error::GroveDB(e)
1077 if matches!(
1078 e.as_ref(),
1079 GroveError::PathKeyNotFound(_)
1080 | GroveError::PathNotFound(_)
1081 | GroveError::PathParentLayerNotFound(_)
1082 ) =>
1083 {
1084 let error_message = if self.start_at_included {
1085 "startAt document not found"
1086 } else {
1087 "startAfter document not found"
1088 };
1089
1090 Error::Query(QuerySyntaxError::StartDocumentNotFound(error_message))
1091 }
1092 _ => e,
1093 })?
1094 .ok_or(Error::Drive(DriveError::CorruptedCodeExecution(
1095 "expected a value",
1096 )))?;
1097
1098 let path_query =
1099 PathQuery::new_single_key(start_at_document_path, start_at_document_key);
1100
1101 if let Element::Item(item, _) = start_at_document {
1102 let document = Document::from_bytes(
1103 item.as_slice(),
1104 self.document_type,
1105 platform_version,
1106 )?;
1107 Ok((Some((document, self.start_at_included)), Some(path_query)))
1108 } else {
1109 Err(Error::Drive(DriveError::CorruptedDocumentPath(
1110 "Holding paths should only have items",
1111 )))
1112 }
1113 }
1114 }?;
1115 let mut main_path_query = if self.is_for_primary_key() {
1116 self.get_primary_key_path_query(
1117 document_type_path,
1118 starts_at_document,
1119 platform_version,
1120 )
1121 } else {
1122 self.get_non_primary_key_path_query(
1123 document_type_path,
1124 starts_at_document,
1125 platform_version,
1126 )
1127 }?;
1128 if !include_start_at_for_proof {
1129 return Ok(main_path_query);
1130 }
1131
1132 if let Some(start_at_path_query) = start_at_path_query {
1133 let limit = main_path_query.query.limit.take();
1134 let mut merged = PathQuery::merge(
1135 vec![&start_at_path_query, &main_path_query],
1136 &platform_version.drive.grove_version,
1137 )
1138 .map_err(Error::from)?;
1139 merged.query.limit = limit.map(|a| a.saturating_add(1));
1140 Ok(merged)
1141 } else {
1142 Ok(main_path_query)
1143 }
1144 }
1145
1146 #[cfg(any(feature = "server", feature = "verify"))]
1147 pub fn construct_path_query(
1149 &self,
1150 starts_at_document: Option<Document>,
1151 platform_version: &PlatformVersion,
1152 ) -> Result<PathQuery, Error> {
1153 let document_type_path = self
1155 .contract
1156 .document_type_path(self.document_type.name().as_str())
1157 .into_iter()
1158 .map(|a| a.to_vec())
1159 .collect::<Vec<Vec<u8>>>();
1160 let starts_at_document = starts_at_document
1161 .map(|starts_at_document| (starts_at_document, self.start_at_included));
1162 if self.is_for_primary_key() {
1163 self.get_primary_key_path_query(
1164 document_type_path,
1165 starts_at_document,
1166 platform_version,
1167 )
1168 } else {
1169 self.get_non_primary_key_path_query(
1170 document_type_path,
1171 starts_at_document,
1172 platform_version,
1173 )
1174 }
1175 }
1176
1177 #[cfg(any(feature = "server", feature = "verify"))]
1178 pub fn get_primary_key_path_query(
1180 &self,
1181 document_type_path: Vec<Vec<u8>>,
1182 starts_at_document: Option<(Document, bool)>,
1183 platform_version: &PlatformVersion,
1184 ) -> Result<PathQuery, Error> {
1185 let mut path = document_type_path;
1186
1187 path.push(vec![0]);
1189
1190 if let Some(primary_key_equal_clause) = &self.internal_clauses.primary_key_equal_clause {
1191 let mut query = Query::new();
1192 let key = self.document_type.serialize_value_for_key(
1193 "$id",
1194 &primary_key_equal_clause.value,
1195 platform_version,
1196 )?;
1197 query.insert_key(key);
1198
1199 if self.document_type.documents_keep_history() {
1200 if let Some(block_time) = self.block_time_ms {
1202 let encoded_block_time = encode_u64(block_time);
1203 let mut sub_query = Query::new_with_direction(false);
1204 sub_query.insert_range_to_inclusive(..=encoded_block_time);
1205 query.set_subquery(sub_query);
1206 } else {
1207 query.set_subquery_key(vec![0]);
1208 }
1209 }
1210
1211 Ok(PathQuery::new(path, SizedQuery::new(query, Some(1), None)))
1212 } else {
1213 let left_to_right = if self.order_by.keys().len() == 1 {
1215 if self.order_by.keys().next().unwrap() != "$id" {
1216 return Err(Error::Query(QuerySyntaxError::InvalidOrderByProperties(
1217 "order by should include $id only",
1218 )));
1219 }
1220
1221 let order_clause = self.order_by.get("$id").unwrap();
1222
1223 order_clause.ascending
1224 } else {
1225 true
1226 };
1227
1228 let mut query = Query::new_with_direction(left_to_right);
1229 let starts_at_key_option = match starts_at_document {
1232 None => None,
1233 Some((document, included)) => {
1234 document
1236 .get_raw_for_document_type(
1237 "$id",
1238 self.document_type,
1239 None,
1240 platform_version,
1241 )?
1242 .map(|raw_value_option| (raw_value_option, included))
1243 }
1244 };
1245
1246 if let Some(primary_key_in_clause) = &self.internal_clauses.primary_key_in_clause {
1247 let in_values = primary_key_in_clause.in_values().into_data_with_error()??;
1248
1249 match starts_at_key_option {
1250 None => {
1251 for value in in_values.iter() {
1252 let key = self.document_type.serialize_value_for_key(
1253 "$id",
1254 value,
1255 platform_version,
1256 )?;
1257 query.insert_key(key)
1258 }
1259 }
1260 Some((starts_at_key, included)) => {
1261 for value in in_values.iter() {
1262 let key = self.document_type.serialize_value_for_key(
1263 "$id",
1264 value,
1265 platform_version,
1266 )?;
1267
1268 if (left_to_right && starts_at_key < key)
1269 || (!left_to_right && starts_at_key > key)
1270 || (included && starts_at_key == key)
1271 {
1272 query.insert_key(key);
1273 }
1274 }
1275 }
1276 }
1277
1278 if self.document_type.documents_keep_history() {
1279 if let Some(_block_time) = self.block_time_ms {
1281 return Err(Error::Query(QuerySyntaxError::Unsupported(
1283 "Not yet implemented".to_string(),
1284 )));
1285 } else {
1293 query.set_subquery_key(vec![0]);
1294 }
1295 }
1296
1297 Ok(PathQuery::new(
1298 path,
1299 SizedQuery::new(query, self.limit, self.offset),
1300 ))
1301 } else {
1302 match starts_at_key_option {
1304 None => {
1305 query.insert_all();
1306 }
1307 Some((starts_at_key, included)) => match left_to_right {
1308 true => match included {
1309 true => query.insert_range_from(starts_at_key..),
1310 false => query.insert_range_after(starts_at_key..),
1311 },
1312 false => match included {
1313 true => query.insert_range_to_inclusive(..=starts_at_key),
1314 false => query.insert_range_to(..starts_at_key),
1315 },
1316 },
1317 }
1318
1319 if self.document_type.documents_keep_history() {
1320 if let Some(_block_time) = self.block_time_ms {
1322 return Err(Error::Query(QuerySyntaxError::Unsupported(
1323 "this query is not supported".to_string(),
1324 )));
1325 } else {
1333 query.set_subquery_key(vec![0]);
1334 }
1335 }
1336
1337 Ok(PathQuery::new(
1338 path,
1339 SizedQuery::new(query, self.limit, self.offset),
1340 ))
1341 }
1342 }
1343 }
1344
1345 #[cfg(any(feature = "server", feature = "verify"))]
1346 pub fn find_best_index(&self, platform_version: &PlatformVersion) -> Result<&Index, Error> {
1348 let equal_fields = self
1349 .internal_clauses
1350 .equal_clauses
1351 .keys()
1352 .map(|s| s.as_str())
1353 .collect::<Vec<&str>>();
1354 let in_field = self
1355 .internal_clauses
1356 .in_clause
1357 .as_ref()
1358 .map(|in_clause| in_clause.field.as_str());
1359 let range_field = self
1360 .internal_clauses
1361 .range_clause
1362 .as_ref()
1363 .map(|range_clause| range_clause.field.as_str());
1364 let mut fields = equal_fields;
1365 if let Some(range_field) = range_field {
1366 fields.push(range_field);
1367 }
1368 if let Some(in_field) = in_field {
1369 fields.push(in_field);
1370 }
1372
1373 let order_by_keys: Vec<&str> = self
1374 .order_by
1375 .keys()
1376 .map(|key: &String| {
1377 let str = key.as_str();
1378 if !fields.contains(&str) {
1379 fields.push(str);
1380 }
1381 str
1382 })
1383 .collect();
1384
1385 let (index, difference) = self
1386 .document_type
1387 .index_for_types(
1388 fields.as_slice(),
1389 in_field,
1390 order_by_keys.as_slice(),
1391 platform_version,
1392 )?
1393 .ok_or(Error::Query(
1394 QuerySyntaxError::WhereClauseOnNonIndexedProperty(format!(
1395 "query must be for valid indexes, valid indexes are: {:?}",
1396 self.document_type.indexes()
1397 )),
1398 ))?;
1399 if difference > defaults::MAX_INDEX_DIFFERENCE {
1400 return Err(Error::Query(QuerySyntaxError::QueryTooFarFromIndex(
1401 "query must better match an existing index",
1402 )));
1403 }
1404 Ok(index)
1405 }
1406
1407 #[cfg(any(feature = "server", feature = "verify"))]
1408 pub fn query_item_for_starts_at_key(starts_at_key: Vec<u8>, left_to_right: bool) -> QueryItem {
1410 if left_to_right {
1411 QueryItem::RangeAfter(starts_at_key..)
1412 } else {
1413 QueryItem::RangeTo(..starts_at_key)
1414 }
1415 }
1416
1417 #[cfg(any(feature = "server", feature = "verify"))]
1418 fn inner_query_from_starts_at_for_id(
1420 starts_at_document: Option<&StartAtDocument>,
1421 left_to_right: bool,
1422 ) -> Query {
1423 let mut inner_query = Query::new_with_direction(left_to_right);
1425
1426 if let Some(StartAtDocument {
1427 document, included, ..
1428 }) = starts_at_document
1429 {
1430 let start_at_key = document.id().to_vec();
1431 if *included {
1432 inner_query.insert_range_from(start_at_key..)
1433 } else {
1434 inner_query.insert_range_after(start_at_key..)
1435 }
1436 } else {
1437 inner_query.insert_all();
1439 }
1440 inner_query
1441 }
1442
1443 #[cfg(any(feature = "server", feature = "verify"))]
1444 fn inner_query_starts_from_key(
1446 start_at_key: Option<Vec<u8>>,
1447 left_to_right: bool,
1448 included: bool,
1449 ) -> Query {
1450 let mut inner_query = Query::new_with_direction(left_to_right);
1452
1453 if left_to_right {
1454 if let Some(start_at_key) = start_at_key {
1455 if included {
1456 inner_query.insert_range_from(start_at_key..);
1457 } else {
1458 inner_query.insert_range_after(start_at_key..);
1459 }
1460 } else {
1461 inner_query.insert_all();
1462 }
1463 } else if included {
1464 if let Some(start_at_key) = start_at_key {
1465 inner_query.insert_range_to_inclusive(..=start_at_key);
1466 } else {
1467 inner_query.insert_key(vec![]);
1468 }
1469 } else if let Some(start_at_key) = start_at_key {
1470 inner_query.insert_range_to(..start_at_key);
1471 } else {
1472 inner_query.insert_key(vec![]);
1475 }
1476
1477 inner_query
1478 }
1479
1480 #[cfg(any(feature = "server", feature = "verify"))]
1481 fn inner_query_from_starts_at(
1483 starts_at_document: Option<&StartAtDocument>,
1484 indexed_property: &IndexProperty,
1485 left_to_right: bool,
1486 platform_version: &PlatformVersion,
1487 ) -> Result<Query, Error> {
1488 let mut inner_query = Query::new_with_direction(left_to_right);
1489 if let Some(StartAtDocument {
1490 document,
1491 document_type,
1492 included,
1493 }) = starts_at_document
1494 {
1495 let start_at_key = document.get_raw_for_document_type(
1497 indexed_property.name.as_str(),
1498 *document_type,
1499 None,
1500 platform_version,
1501 )?;
1502 if let Some(start_at_key) = start_at_key {
1504 if left_to_right {
1505 if *included {
1506 inner_query.insert_range_from(start_at_key..)
1507 } else {
1508 inner_query.insert_range_after(start_at_key..)
1509 }
1510 } else if *included {
1511 inner_query.insert_range_to_inclusive(..=start_at_key)
1512 } else {
1513 inner_query.insert_range_to(..start_at_key)
1514 }
1515 } else if left_to_right {
1516 inner_query.insert_all();
1517 } else {
1518 inner_query.insert_key(vec![]);
1519 }
1520 } else {
1521 inner_query.insert_all();
1523 }
1524 Ok(inner_query)
1525 }
1526
1527 #[cfg(any(feature = "server", feature = "verify"))]
1528 fn recursive_create_query(
1529 left_over_index_properties: &[&IndexProperty],
1530 unique: bool,
1531 starts_at_document: Option<&StartAtDocument>, indexed_property: &IndexProperty,
1533 order_by: Option<&IndexMap<String, OrderClause>>,
1534 platform_version: &PlatformVersion,
1535 ) -> Result<Option<Query>, Error> {
1536 match left_over_index_properties.split_first() {
1537 None => Ok(None),
1538 Some((first, left_over)) => {
1539 let left_to_right = if let Some(order_by) = order_by {
1540 order_by
1541 .get(first.name.as_str())
1542 .map(|order_clause| order_clause.ascending)
1543 .unwrap_or(first.ascending)
1544 } else {
1545 first.ascending
1546 };
1547
1548 let mut inner_query = Self::inner_query_from_starts_at(
1549 starts_at_document,
1550 indexed_property,
1551 left_to_right,
1552 platform_version,
1553 )?;
1554 DriveDocumentQuery::recursive_insert_on_query(
1555 &mut inner_query,
1556 left_over,
1557 unique,
1558 starts_at_document,
1559 left_to_right,
1560 order_by,
1561 platform_version,
1562 )?;
1563 Ok(Some(inner_query))
1564 }
1565 }
1566 }
1567
1568 #[cfg(any(feature = "server", feature = "verify"))]
1569 fn recursive_insert_on_query(
1650 query: &mut Query,
1651 left_over_index_properties: &[&IndexProperty],
1652 unique: bool,
1653 starts_at_document: Option<&StartAtDocument>, default_left_to_right: bool,
1655 order_by: Option<&IndexMap<String, OrderClause>>,
1656 platform_version: &PlatformVersion,
1657 ) -> Result<Option<Query>, Error> {
1658 match left_over_index_properties.split_first() {
1659 None => {
1660 match unique {
1661 true => {
1662 query.set_subquery_key(vec![0]);
1663
1664 let inner_query = Self::inner_query_from_starts_at_for_id(
1666 starts_at_document,
1667 true, );
1669 query.add_conditional_subquery(
1670 QueryItem::Key(b"".to_vec()),
1671 Some(vec![vec![0]]),
1672 Some(inner_query),
1673 );
1674 }
1675 false => {
1676 query.set_subquery_key(vec![0]);
1677 let full_query =
1679 Self::inner_query_from_starts_at_for_id(None, default_left_to_right);
1680 query.set_subquery(full_query);
1681
1682 let inner_query = Self::inner_query_from_starts_at_for_id(
1683 starts_at_document,
1684 default_left_to_right,
1685 );
1686
1687 query.add_conditional_subquery(
1688 QueryItem::Key(b"".to_vec()),
1689 Some(vec![vec![0]]),
1690 Some(inner_query),
1691 );
1692 }
1693 }
1694 Ok(None)
1695 }
1696 Some((first, left_over)) => {
1697 let left_to_right = if let Some(order_by) = order_by {
1698 order_by
1699 .get(first.name.as_str())
1700 .map(|order_clause| order_clause.ascending)
1701 .unwrap_or(first.ascending)
1702 } else {
1703 first.ascending
1704 };
1705
1706 if let Some(start_at_document_inner) = starts_at_document {
1707 let StartAtDocument {
1708 document,
1709 document_type,
1710 included,
1711 } = start_at_document_inner;
1712 let start_at_key = document
1713 .get_raw_for_document_type(
1714 first.name.as_str(),
1715 *document_type,
1716 None,
1717 platform_version,
1718 )
1719 .ok()
1720 .flatten();
1721
1722 let non_conditional_included =
1724 !left_over.is_empty() || *included || start_at_key.is_none();
1725
1726 let mut non_conditional_query = Self::inner_query_starts_from_key(
1727 start_at_key.clone(),
1728 left_to_right,
1729 non_conditional_included,
1730 );
1731
1732 DriveDocumentQuery::recursive_insert_on_query(
1777 &mut non_conditional_query,
1778 left_over,
1779 unique,
1780 None,
1781 left_to_right,
1782 order_by,
1783 platform_version,
1784 )?;
1785
1786 DriveDocumentQuery::recursive_conditional_insert_on_query(
1787 &mut non_conditional_query,
1788 start_at_key,
1789 left_over,
1790 unique,
1791 start_at_document_inner,
1792 left_to_right,
1793 order_by,
1794 platform_version,
1795 )?;
1796
1797 query.set_subquery(non_conditional_query);
1798 } else {
1799 let mut inner_query = Query::new_with_direction(first.ascending);
1800 inner_query.insert_all();
1801 DriveDocumentQuery::recursive_insert_on_query(
1802 &mut inner_query,
1803 left_over,
1804 unique,
1805 starts_at_document,
1806 left_to_right,
1807 order_by,
1808 platform_version,
1809 )?;
1810 query.set_subquery(inner_query);
1811 }
1812 query.set_subquery_key(first.name.as_bytes().to_vec());
1813 Ok(None)
1814 }
1815 }
1816 }
1817
1818 #[cfg(any(feature = "server", feature = "verify"))]
1819 #[allow(clippy::too_many_arguments)]
1820 fn recursive_conditional_insert_on_query(
1821 query: &mut Query,
1822 conditional_value: Option<Vec<u8>>,
1823 left_over_index_properties: &[&IndexProperty],
1824 unique: bool,
1825 starts_at_document: &StartAtDocument,
1826 default_left_to_right: bool,
1827 order_by: Option<&IndexMap<String, OrderClause>>,
1828 platform_version: &PlatformVersion,
1829 ) -> Result<(), Error> {
1830 match left_over_index_properties.split_first() {
1831 None => {
1832 match unique {
1833 true => {
1834 let inner_query = Self::inner_query_from_starts_at_for_id(
1836 Some(starts_at_document),
1837 true, );
1839 query.add_conditional_subquery(
1840 QueryItem::Key(b"".to_vec()),
1841 Some(vec![vec![0]]),
1842 Some(inner_query),
1843 );
1844 }
1845 false => {
1846 let inner_query = Self::inner_query_from_starts_at_for_id(
1847 Some(starts_at_document),
1848 default_left_to_right,
1849 );
1850
1851 query.add_conditional_subquery(
1852 QueryItem::Key(conditional_value.unwrap_or_default()),
1853 Some(vec![vec![0]]),
1854 Some(inner_query),
1855 );
1856 }
1857 }
1858 }
1859 Some((first, left_over)) => {
1860 let left_to_right = if let Some(order_by) = order_by {
1861 order_by
1862 .get(first.name.as_str())
1863 .map(|order_clause| order_clause.ascending)
1864 .unwrap_or(first.ascending)
1865 } else {
1866 first.ascending
1867 };
1868
1869 let StartAtDocument {
1870 document,
1871 document_type,
1872 ..
1873 } = starts_at_document;
1874
1875 let lower_start_at_key = document
1876 .get_raw_for_document_type(
1877 first.name.as_str(),
1878 *document_type,
1879 None,
1880 platform_version,
1881 )
1882 .ok()
1883 .flatten();
1884
1885 let non_conditional_included = !unique || lower_start_at_key.is_none();
1888
1889 let mut non_conditional_query = Self::inner_query_starts_from_key(
1890 lower_start_at_key.clone(),
1891 left_to_right,
1892 non_conditional_included,
1893 );
1894
1895 DriveDocumentQuery::recursive_insert_on_query(
1896 &mut non_conditional_query,
1897 left_over,
1898 unique,
1899 None,
1900 left_to_right,
1901 order_by,
1902 platform_version,
1903 )?;
1904
1905 DriveDocumentQuery::recursive_conditional_insert_on_query(
1906 &mut non_conditional_query,
1907 lower_start_at_key,
1908 left_over,
1909 unique,
1910 starts_at_document,
1911 left_to_right,
1912 order_by,
1913 platform_version,
1914 )?;
1915
1916 query.add_conditional_subquery(
1917 QueryItem::Key(conditional_value.unwrap_or_default()),
1918 Some(vec![first.name.as_bytes().to_vec()]),
1919 Some(non_conditional_query),
1920 );
1921 }
1922 }
1923 Ok(())
1924 }
1925
1926 #[cfg(any(feature = "server", feature = "verify"))]
1927 pub fn get_non_primary_key_path_query(
1929 &self,
1930 document_type_path: Vec<Vec<u8>>,
1931 starts_at_document: Option<(Document, bool)>,
1932 platform_version: &PlatformVersion,
1933 ) -> Result<PathQuery, Error> {
1934 let index = self.find_best_index(platform_version)?;
1935 let ordered_clauses: Vec<&WhereClause> = index
1936 .properties
1937 .iter()
1938 .filter_map(|field| self.internal_clauses.equal_clauses.get(field.name.as_str()))
1939 .collect();
1940 let (last_clause, last_clause_is_range, subquery_clause) = match &self
1941 .internal_clauses
1942 .in_clause
1943 {
1944 None => match &self.internal_clauses.range_clause {
1945 None => (ordered_clauses.last().copied(), false, None),
1946 Some(where_clause) => (Some(where_clause), true, None),
1947 },
1948 Some(in_clause) => match &self.internal_clauses.range_clause {
1949 None => (Some(in_clause), true, None),
1950 Some(range_clause) => {
1951 let position_of = |field: &str| -> Option<usize> {
1962 index
1963 .properties
1964 .iter()
1965 .position(|p| p.name.as_str() == field)
1966 };
1967 let in_pos = position_of(in_clause.field.as_str());
1968 let range_pos = position_of(range_clause.field.as_str());
1969 match (in_pos, range_pos) {
1970 (Some(i), Some(r)) if i > r => (Some(range_clause), true, Some(in_clause)),
1971 _ => (Some(in_clause), true, Some(range_clause)),
1972 }
1973 }
1974 },
1975 };
1976
1977 let left_over_index_properties = index
1979 .properties
1980 .iter()
1981 .filter(|field| {
1982 !(self
1983 .internal_clauses
1984 .equal_clauses
1985 .contains_key(field.name.as_str())
1986 || (last_clause.is_some() && last_clause.unwrap().field == field.name)
1987 || (subquery_clause.is_some() && subquery_clause.unwrap().field == field.name))
1988 })
1989 .collect::<Vec<&IndexProperty>>();
1990
1991 let intermediate_values = index
1992 .properties
1993 .iter()
1994 .filter_map(|field| {
1995 match self.internal_clauses.equal_clauses.get(field.name.as_str()) {
1996 None => None,
1997 Some(where_clause) => {
1998 if !last_clause_is_range
1999 && last_clause.is_some()
2000 && last_clause.unwrap().field == field.name
2001 {
2002 None
2004 } else {
2005 Some(self.document_type.serialize_value_for_key(
2006 field.name.as_str(),
2007 &where_clause.value,
2008 platform_version,
2009 ))
2010 }
2011 }
2012 }
2013 })
2014 .collect::<Result<Vec<Vec<u8>>, ProtocolError>>()
2015 .map_err(Error::from)?;
2016
2017 let final_query = match last_clause {
2018 None => {
2019 let first_index = index.properties.first().ok_or(Error::Drive(
2022 DriveError::CorruptedContractIndexes("index must have properties".to_string()),
2023 ))?; Self::recursive_create_query(
2025 left_over_index_properties.as_slice(),
2026 index.unique,
2027 starts_at_document
2028 .map(|(document, included)| StartAtDocument {
2029 document,
2030 document_type: self.document_type,
2031 included,
2032 })
2033 .as_ref(),
2034 first_index,
2035 Some(&self.order_by),
2036 platform_version,
2037 )?
2038 .expect("Index must have left over properties if no last clause")
2039 }
2040 Some(where_clause) => {
2041 let left_to_right = if where_clause.operator.is_range() {
2042 let order_clause: &OrderClause = self
2043 .order_by
2044 .get(where_clause.field.as_str())
2045 .ok_or(Error::Query(QuerySyntaxError::MissingOrderByForRange(
2046 "query must have an orderBy field for each range element",
2047 )))?;
2048
2049 order_clause.ascending
2050 } else {
2051 true
2052 };
2053
2054 let query_starts_at_document = if left_over_index_properties.is_empty() {
2058 &starts_at_document
2059 } else {
2060 &None
2061 };
2062
2063 let mut query = where_clause.to_path_query(
2064 self.document_type,
2065 query_starts_at_document,
2066 left_to_right,
2067 platform_version,
2068 )?;
2069
2070 match subquery_clause {
2071 None => {
2072 Self::recursive_insert_on_query(
2073 &mut query,
2074 left_over_index_properties.as_slice(),
2075 index.unique,
2076 starts_at_document
2077 .map(|(document, included)| StartAtDocument {
2078 document,
2079 document_type: self.document_type,
2080 included,
2081 })
2082 .as_ref(),
2083 left_to_right,
2084 Some(&self.order_by),
2085 platform_version,
2086 )?;
2087 }
2088 Some(subquery_where_clause) => {
2089 let order_clause: &OrderClause = self
2090 .order_by
2091 .get(subquery_where_clause.field.as_str())
2092 .ok_or(Error::Query(QuerySyntaxError::MissingOrderByForRange(
2093 "query must have an orderBy field for each range element",
2094 )))?;
2095 let mut subquery = subquery_where_clause.to_path_query(
2096 self.document_type,
2097 &starts_at_document,
2098 order_clause.ascending,
2099 platform_version,
2100 )?;
2101 Self::recursive_insert_on_query(
2102 &mut subquery,
2103 left_over_index_properties.as_slice(),
2104 index.unique,
2105 starts_at_document
2106 .map(|(document, included)| StartAtDocument {
2107 document,
2108 document_type: self.document_type,
2109 included,
2110 })
2111 .as_ref(),
2112 left_to_right,
2113 Some(&self.order_by),
2114 platform_version,
2115 )?;
2116 let subindex = subquery_where_clause.field.as_bytes().to_vec();
2117 query.set_subquery_key(subindex);
2118 query.set_subquery(subquery);
2119 }
2120 };
2121
2122 query
2123 }
2124 };
2125
2126 let (intermediate_indexes, last_indexes) =
2127 index.properties.split_at(intermediate_values.len());
2128
2129 let last_index = last_indexes.first().ok_or(Error::Query(
2131 QuerySyntaxError::QueryOnDocumentTypeWithNoIndexes(
2132 "document query has no index with fields",
2133 ),
2134 ))?;
2135
2136 let mut path = document_type_path;
2137
2138 for (intermediate_index, intermediate_value) in
2139 intermediate_indexes.iter().zip(intermediate_values.iter())
2140 {
2141 path.push(intermediate_index.name.as_bytes().to_vec());
2142 path.push(intermediate_value.as_slice().to_vec());
2143 }
2144
2145 path.push(last_index.name.as_bytes().to_vec());
2146
2147 Ok(PathQuery::new(
2148 path,
2149 SizedQuery::new(final_query, self.limit, self.offset),
2150 ))
2151 }
2152
2153 #[cfg(feature = "server")]
2154 pub fn execute_with_proof(
2156 self,
2157 drive: &Drive,
2158 block_info: Option<BlockInfo>,
2159 transaction: TransactionArg,
2160 platform_version: &PlatformVersion,
2161 ) -> Result<(Vec<u8>, u64), Error> {
2162 let mut drive_operations = vec![];
2163 let items = self.execute_with_proof_internal(
2164 drive,
2165 transaction,
2166 &mut drive_operations,
2167 platform_version,
2168 )?;
2169 let cost = if let Some(block_info) = block_info {
2170 let fee_result = Drive::calculate_fee(
2171 None,
2172 Some(drive_operations),
2173 &block_info.epoch,
2174 drive.config.epochs_per_era,
2175 platform_version,
2176 None,
2177 )?;
2178 fee_result.processing_fee
2179 } else {
2180 0
2181 };
2182 Ok((items, cost))
2183 }
2184
2185 #[cfg(feature = "server")]
2186 pub(crate) fn execute_with_proof_internal(
2188 self,
2189 drive: &Drive,
2190 transaction: TransactionArg,
2191 drive_operations: &mut Vec<LowLevelDriveOperation>,
2192 platform_version: &PlatformVersion,
2193 ) -> Result<Vec<u8>, Error> {
2194 let path_query = self.construct_path_query_operations(
2195 drive,
2196 true,
2197 transaction,
2198 drive_operations,
2199 platform_version,
2200 )?;
2201 drive.grove_get_proved_path_query(
2202 &path_query,
2203 transaction,
2204 drive_operations,
2205 &platform_version.drive,
2206 )
2207 }
2208
2209 #[cfg(all(feature = "server", feature = "verify"))]
2210 pub fn execute_with_proof_only_get_elements(
2212 self,
2213 drive: &Drive,
2214 block_info: Option<BlockInfo>,
2215 transaction: TransactionArg,
2216 platform_version: &PlatformVersion,
2217 ) -> Result<(RootHash, Vec<Vec<u8>>, u64), Error> {
2218 let mut drive_operations = vec![];
2219 let (root_hash, items) = self.execute_with_proof_only_get_elements_internal(
2220 drive,
2221 transaction,
2222 &mut drive_operations,
2223 platform_version,
2224 )?;
2225 let cost = if let Some(block_info) = block_info {
2226 let fee_result = Drive::calculate_fee(
2227 None,
2228 Some(drive_operations),
2229 &block_info.epoch,
2230 drive.config.epochs_per_era,
2231 platform_version,
2232 None,
2233 )?;
2234 fee_result.processing_fee
2235 } else {
2236 0
2237 };
2238 Ok((root_hash, items, cost))
2239 }
2240
2241 #[cfg(all(feature = "server", feature = "verify"))]
2242 pub(crate) fn execute_with_proof_only_get_elements_internal(
2244 self,
2245 drive: &Drive,
2246 transaction: TransactionArg,
2247 drive_operations: &mut Vec<LowLevelDriveOperation>,
2248 platform_version: &PlatformVersion,
2249 ) -> Result<(RootHash, Vec<Vec<u8>>), Error> {
2250 let path_query = self.construct_path_query_operations(
2251 drive,
2252 true,
2253 transaction,
2254 drive_operations,
2255 platform_version,
2256 )?;
2257
2258 let proof = drive.grove_get_proved_path_query(
2259 &path_query,
2260 transaction,
2261 drive_operations,
2262 &platform_version.drive,
2263 )?;
2264 self.verify_proof_keep_serialized(proof.as_slice(), platform_version)
2265 }
2266
2267 #[cfg(feature = "server")]
2268 pub fn execute_raw_results_no_proof(
2270 &self,
2271 drive: &Drive,
2272 block_info: Option<BlockInfo>,
2273 transaction: TransactionArg,
2274 platform_version: &PlatformVersion,
2275 ) -> Result<(Vec<Vec<u8>>, u16, u64), Error> {
2276 let mut drive_operations = vec![];
2277 let (items, skipped) = self.execute_raw_results_no_proof_internal(
2278 drive,
2279 transaction,
2280 &mut drive_operations,
2281 platform_version,
2282 )?;
2283 let cost = if let Some(block_info) = block_info {
2284 let fee_result = Drive::calculate_fee(
2285 None,
2286 Some(drive_operations),
2287 &block_info.epoch,
2288 drive.config.epochs_per_era,
2289 platform_version,
2290 None,
2291 )?;
2292 fee_result.processing_fee
2293 } else {
2294 0
2295 };
2296 Ok((items, skipped, cost))
2297 }
2298
2299 #[cfg(feature = "server")]
2300 pub(crate) fn execute_raw_results_no_proof_internal(
2302 &self,
2303 drive: &Drive,
2304 transaction: TransactionArg,
2305 drive_operations: &mut Vec<LowLevelDriveOperation>,
2306 platform_version: &PlatformVersion,
2307 ) -> Result<(Vec<Vec<u8>>, u16), Error> {
2308 let path_query = self.construct_path_query_operations(
2309 drive,
2310 false,
2311 transaction,
2312 drive_operations,
2313 platform_version,
2314 )?;
2315
2316 let query_result = drive.grove_get_path_query_serialized_results(
2317 &path_query,
2318 transaction,
2319 drive_operations,
2320 &platform_version.drive,
2321 );
2322 match query_result {
2323 Err(Error::GroveDB(e))
2324 if matches!(
2325 e.as_ref(),
2326 GroveError::PathKeyNotFound(_)
2327 | GroveError::PathNotFound(_)
2328 | GroveError::PathParentLayerNotFound(_)
2329 ) =>
2330 {
2331 Ok((Vec::new(), 0))
2332 }
2333 _ => {
2334 let (data, skipped) = query_result?;
2335 {
2336 Ok((data, skipped))
2337 }
2338 }
2339 }
2340 }
2341
2342 #[cfg(feature = "server")]
2343 pub(crate) fn execute_no_proof_internal(
2345 &self,
2346 drive: &Drive,
2347 result_type: QueryResultType,
2348 transaction: TransactionArg,
2349 drive_operations: &mut Vec<LowLevelDriveOperation>,
2350 platform_version: &PlatformVersion,
2351 ) -> Result<(QueryResultElements, u16), Error> {
2352 let path_query = self.construct_path_query_operations(
2353 drive,
2354 false,
2355 transaction,
2356 drive_operations,
2357 platform_version,
2358 )?;
2359 let query_result = drive.grove_get_path_query(
2360 &path_query,
2361 transaction,
2362 result_type,
2363 drive_operations,
2364 &platform_version.drive,
2365 );
2366 match query_result {
2367 Err(Error::GroveDB(e))
2368 if matches!(
2369 e.as_ref(),
2370 GroveError::PathKeyNotFound(_)
2371 | GroveError::PathNotFound(_)
2372 | GroveError::PathParentLayerNotFound(_)
2373 ) =>
2374 {
2375 Ok((QueryResultElements::new(), 0))
2376 }
2377 _ => {
2378 let (data, skipped) = query_result?;
2379 {
2380 Ok((data, skipped))
2381 }
2382 }
2383 }
2384 }
2385}
2386
2387impl<'a> From<&DriveDocumentQuery<'a>> for BTreeMap<String, Value> {
2389 fn from(query: &DriveDocumentQuery<'a>) -> Self {
2390 let mut response = BTreeMap::<String, Value>::new();
2391
2392 response.insert(
2395 "contract_id".to_string(),
2396 Value::Identifier(query.contract.id().to_buffer()),
2397 );
2398
2399 response.insert(
2402 "document_type_name".to_string(),
2403 Value::Text(query.document_type.name().to_string()),
2404 );
2405
2406 let all_where_clauses: Vec<WhereClause> = query.internal_clauses.clone().into();
2408 response.insert(
2409 "where".to_string(),
2410 Value::Array(all_where_clauses.into_iter().map(|v| v.into()).collect()),
2411 );
2412
2413 if let Some(offset) = query.offset {
2415 response.insert("offset".to_string(), Value::U16(offset));
2416 };
2417 if let Some(limit) = query.limit {
2419 response.insert("limit".to_string(), Value::U16(limit));
2420 };
2421 let order_by = &query.order_by;
2423 let value: Vec<Value> = order_by
2424 .into_iter()
2425 .map(|(_k, v)| v.clone().into())
2426 .collect();
2427 response.insert("orderBy".to_string(), Value::Array(value));
2428
2429 if let Some(start_at) = query.start_at {
2431 let v = Value::Identifier(start_at);
2432 if query.start_at_included {
2433 response.insert("startAt".to_string(), v);
2434 } else {
2435 response.insert("startAfter".to_string(), v);
2436 }
2437 };
2438
2439 if let Some(block_time_ms) = query.block_time_ms {
2441 response.insert("blockTime".to_string(), Value::U64(block_time_ms));
2442 };
2443
2444 response
2445 }
2446}
2447
2448#[cfg(feature = "server")]
2449#[cfg(test)]
2450mod tests {
2451
2452 use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
2453
2454 use dpp::prelude::Identifier;
2455 use grovedb::Query;
2456 use indexmap::IndexMap;
2457 use rand::prelude::StdRng;
2458 use rand::SeedableRng;
2459 use serde_json::json;
2460 use std::borrow::Cow;
2461 use std::collections::BTreeMap;
2462 use std::option::Option::None;
2463 use tempfile::TempDir;
2464
2465 use crate::drive::Drive;
2466 use crate::query::{
2467 DriveDocumentQuery, InternalClauses, OrderClause, WhereClause, WhereOperator,
2468 };
2469 use crate::util::storage_flags::StorageFlags;
2470
2471 use dpp::data_contract::DataContract;
2472
2473 use serde_json::Value::Null;
2474
2475 use crate::config::DriveConfig;
2476 use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure;
2477 use dpp::block::block_info::BlockInfo;
2478 use dpp::data_contract::accessors::v0::DataContractV0Getters;
2479 use dpp::data_contracts::SystemDataContract;
2480 use dpp::document::DocumentV0;
2481 use dpp::platform_value::string_encoding::Encoding;
2482 use dpp::platform_value::Value;
2483 use dpp::system_data_contracts::load_system_data_contract;
2484 use dpp::tests::fixtures::{get_data_contract_fixture, get_dpns_data_contract_fixture};
2485 use dpp::tests::json_document::json_document_to_contract;
2486 use dpp::util::cbor_serializer;
2487 use dpp::version::PlatformVersion;
2488
2489 fn setup_family_contract() -> (Drive, DataContract) {
2490 let tmp_dir = TempDir::new().unwrap();
2491
2492 let platform_version = PlatformVersion::latest();
2493
2494 let (drive, _) = Drive::open(tmp_dir, None).expect("expected to open Drive successfully");
2495
2496 drive
2497 .create_initial_state_structure(None, platform_version)
2498 .expect("expected to create root tree successfully");
2499
2500 let contract_path = "tests/supporting_files/contract/family/family-contract.json";
2501
2502 let contract = json_document_to_contract(contract_path, false, platform_version)
2504 .expect("expected to get document");
2505
2506 let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0)));
2507 drive
2508 .apply_contract(
2509 &contract,
2510 BlockInfo::default(),
2511 true,
2512 storage_flags,
2513 None,
2514 platform_version,
2515 )
2516 .expect("expected to apply contract successfully");
2517
2518 (drive, contract)
2519 }
2520
2521 fn setup_withdrawal_contract() -> (Drive, DataContract) {
2522 let tmp_dir = TempDir::new().unwrap();
2523
2524 let platform_version = PlatformVersion::latest();
2525
2526 let (drive, _) = Drive::open(tmp_dir, None).expect("expected to open Drive successfully");
2527
2528 drive
2529 .create_initial_state_structure(None, platform_version)
2530 .expect("expected to create root tree successfully");
2531
2532 let contract = load_system_data_contract(SystemDataContract::Withdrawals, platform_version)
2534 .expect("load system contact");
2535
2536 let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0)));
2537 drive
2538 .apply_contract(
2539 &contract,
2540 BlockInfo::default(),
2541 true,
2542 storage_flags,
2543 None,
2544 platform_version,
2545 )
2546 .expect("expected to apply contract successfully");
2547
2548 (drive, contract)
2549 }
2550
2551 fn setup_family_birthday_contract() -> (Drive, DataContract) {
2552 let drive = setup_drive_with_initial_state_structure(None);
2553
2554 let platform_version = PlatformVersion::latest();
2555
2556 let contract_path =
2557 "tests/supporting_files/contract/family/family-contract-with-birthday.json";
2558
2559 let contract = json_document_to_contract(contract_path, false, platform_version)
2561 .expect("expected to get document");
2562 let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0)));
2563 drive
2564 .apply_contract(
2565 &contract,
2566 BlockInfo::default(),
2567 true,
2568 storage_flags,
2569 None,
2570 platform_version,
2571 )
2572 .expect("expected to apply contract successfully");
2573
2574 (drive, contract)
2575 }
2576
2577 #[test]
2578 fn test_drive_query_from_to_cbor() {
2579 let config = DriveConfig::default();
2580 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2581 let document_type = contract
2582 .document_type_for_name("niceDocument")
2583 .expect("expected to get nice document");
2584 let start_after = Identifier::random();
2585
2586 let query_value = json!({
2587 "contract_id": contract.id(),
2588 "document_type_name": document_type.name(),
2589 "where": [
2590 ["firstName", "<", "Gilligan"],
2591 ["lastName", "=", "Doe"]
2592 ],
2593 "limit": 100u16,
2594 "offset": 10u16,
2595 "orderBy": [
2596 ["firstName", "asc"],
2597 ["lastName", "desc"],
2598 ],
2599 "startAfter": start_after,
2600 "blockTime": 13453432u64,
2601 });
2602
2603 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2604 .expect("expected to serialize to cbor");
2605 let query =
2606 DriveDocumentQuery::from_cbor(where_cbor.as_slice(), &contract, document_type, &config)
2607 .expect("deserialize cbor shouldn't fail");
2608
2609 let cbor = query.to_cbor().expect("should serialize cbor");
2610
2611 let deserialized = DriveDocumentQuery::from_cbor(&cbor, &contract, document_type, &config)
2612 .expect("should deserialize cbor");
2613
2614 assert_eq!(query, deserialized);
2615
2616 assert_eq!(deserialized.start_at, Some(start_after.to_buffer()));
2617 assert!(!deserialized.start_at_included);
2618 assert_eq!(deserialized.block_time_ms, Some(13453432u64));
2619 }
2620
2621 #[test]
2622 fn test_invalid_query_ranges_different_fields() {
2623 let query_value = json!({
2624 "where": [
2625 ["firstName", "<", "Gilligan"],
2626 ["lastName", "<", "Michelle"],
2627 ],
2628 "limit": 100,
2629 "orderBy": [
2630 ["firstName", "asc"],
2631 ["lastName", "asc"],
2632 ]
2633 });
2634 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2635 let document_type = contract
2636 .document_type_for_name("niceDocument")
2637 .expect("expected to get nice document");
2638
2639 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2640 .expect("expected to serialize to cbor");
2641 DriveDocumentQuery::from_cbor(
2642 where_cbor.as_slice(),
2643 &contract,
2644 document_type,
2645 &DriveConfig::default(),
2646 )
2647 .expect_err("all ranges must be on same field");
2648 }
2649
2650 #[test]
2651 fn test_invalid_query_extra_invalid_field() {
2652 let query_value = json!({
2653 "where": [
2654 ["firstName", "<", "Gilligan"],
2655 ],
2656 "limit": 100,
2657 "orderBy": [
2658 ["firstName", "asc"],
2659 ["lastName", "asc"],
2660 ],
2661 "invalid": 0,
2662 });
2663 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2664 let document_type = contract
2665 .document_type_for_name("niceDocument")
2666 .expect("expected to get nice document");
2667
2668 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2669 .expect("expected to serialize to cbor");
2670 DriveDocumentQuery::from_cbor(
2671 where_cbor.as_slice(),
2672 &contract,
2673 document_type,
2674 &DriveConfig::default(),
2675 )
2676 .expect_err("fields of queries must of defined supported types (where, limit, orderBy...)");
2677 }
2678
2679 #[test]
2680 fn test_invalid_query_conflicting_clauses() {
2681 let query_value = json!({
2682 "where": [
2683 ["firstName", "<", "Gilligan"],
2684 ["firstName", ">", "Gilligan"],
2685 ],
2686 "limit": 100,
2687 "orderBy": [
2688 ["firstName", "asc"],
2689 ["lastName", "asc"],
2690 ],
2691 });
2692
2693 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2694 let document_type = contract
2695 .document_type_for_name("niceDocument")
2696 .expect("expected to get nice document");
2697
2698 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2699 .expect("expected to serialize to cbor");
2700 DriveDocumentQuery::from_cbor(
2701 where_cbor.as_slice(),
2702 &contract,
2703 document_type,
2704 &DriveConfig::default(),
2705 )
2706 .expect_err("the query should not be created");
2707 }
2708
2709 #[test]
2710 fn test_valid_query_groupable_meeting_clauses() {
2711 let query_value = json!({
2712 "where": [
2713 ["firstName", "<=", "Gilligan"],
2714 ["firstName", ">", "Gilligan"],
2715 ],
2716 "limit": 100,
2717 "orderBy": [
2718 ["firstName", "asc"],
2719 ["lastName", "asc"],
2720 ],
2721 });
2722
2723 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2724 let document_type = contract
2725 .document_type_for_name("niceDocument")
2726 .expect("expected to get nice document");
2727
2728 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2729 .expect("expected to serialize to cbor");
2730 DriveDocumentQuery::from_cbor(
2731 where_cbor.as_slice(),
2732 &contract,
2733 document_type,
2734 &DriveConfig::default(),
2735 )
2736 .expect("the query should be created");
2737 }
2738
2739 #[test]
2740 fn test_valid_query_query_field_at_max_length() {
2741 let long_string = "t".repeat(255);
2742 let query_value = json!({
2743 "where": [
2744 ["firstName", "<", long_string],
2745 ],
2746 "limit": 100,
2747 "orderBy": [
2748 ["firstName", "asc"],
2749 ["lastName", "asc"],
2750 ],
2751 });
2752 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2753 let document_type = contract
2754 .document_type_for_name("niceDocument")
2755 .expect("expected to get nice document");
2756
2757 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2758 .expect("expected to serialize to cbor");
2759 DriveDocumentQuery::from_cbor(
2760 where_cbor.as_slice(),
2761 &contract,
2762 document_type,
2763 &DriveConfig::default(),
2764 )
2765 .expect("query should be fine for a 255 byte long string");
2766 }
2767
2768 #[test]
2769 fn test_valid_query_drive_document_query() {
2770 let platform_version = PlatformVersion::latest();
2771 let mut rng = StdRng::seed_from_u64(5);
2772 let contract =
2773 get_dpns_data_contract_fixture(Some(Identifier::random_with_rng(&mut rng)), 0, 1)
2774 .data_contract_owned();
2775 let domain = contract
2776 .document_type_for_name("domain")
2777 .expect("expected to get domain");
2778
2779 let query_asc = DriveDocumentQuery {
2780 contract: &contract,
2781 document_type: domain,
2782 internal_clauses: InternalClauses {
2783 primary_key_in_clause: None,
2784 primary_key_equal_clause: None,
2785 in_clause: None,
2786 range_clause: Some(WhereClause {
2787 field: "records.identity".to_string(),
2788 operator: WhereOperator::LessThan,
2789 value: Value::Identifier(
2790 Identifier::from_string(
2791 "AYN4srupPWDrp833iG5qtmaAsbapNvaV7svAdncLN5Rh",
2792 Encoding::Base58,
2793 )
2794 .unwrap()
2795 .to_buffer(),
2796 ),
2797 }),
2798 equal_clauses: BTreeMap::new(),
2799 },
2800 offset: None,
2801 limit: Some(6),
2802 order_by: vec![(
2803 "records.identity".to_string(),
2804 OrderClause {
2805 field: "records.identity".to_string(),
2806 ascending: false,
2807 },
2808 )]
2809 .into_iter()
2810 .collect(),
2811 start_at: None,
2812 start_at_included: false,
2813 block_time_ms: None,
2814 };
2815
2816 let path_query = query_asc
2817 .construct_path_query(None, platform_version)
2818 .expect("expected to create path query");
2819
2820 assert_eq!(path_query.to_string(), "PathQuery { path: [@, 0x1da29f488023e306ff9a680bc9837153fb0778c8ee9c934a87dc0de1d69abd3c, 0x01, domain, 0x7265636f7264732e6964656e74697479], query: SizedQuery { query: Query {\n items: [\n RangeTo(.. 0x8dc201fd7ad7905f8a84d66218e2b387daea7fe4739ae0e21e8c3ee755e6a2c0),\n ],\n default_subquery_branch: SubqueryBranch { subquery_path: [0x00], subquery: Query {\n items: [\n RangeFull,\n ],\n default_subquery_branch: SubqueryBranch { subquery_path: None subquery: None },\n left_to_right: false,\n add_parent_tree_on_subquery: false,\n} },\n conditional_subquery_branches: {\n Key(): SubqueryBranch { subquery_path: [0x00], subquery: Query {\n items: [\n RangeFull,\n ],\n default_subquery_branch: SubqueryBranch { subquery_path: None subquery: None },\n left_to_right: false,\n add_parent_tree_on_subquery: false,\n} },\n },\n left_to_right: false,\n add_parent_tree_on_subquery: false,\n}, limit: 6 } }");
2821
2822 let encoded = bincode::encode_to_vec(&path_query, bincode::config::standard())
2824 .expect("Failed to serialize PathQuery");
2825
2826 let hex_string = hex::encode(encoded);
2828
2829 assert_eq!(hex_string, "050140201da29f488023e306ff9a680bc9837153fb0778c8ee9c934a87dc0de1d69abd3c010106646f6d61696e107265636f7264732e6964656e74697479010105208dc201fd7ad7905f8a84d66218e2b387daea7fe4739ae0e21e8c3ee755e6a2c00101010001010103000000000001010000010101000101010300000000000000010600");
2833 }
2834
2835 #[test]
2836 fn test_invalid_query_field_too_long() {
2837 let (drive, contract) = setup_family_contract();
2838
2839 let platform_version = PlatformVersion::latest();
2840
2841 let document_type = contract
2842 .document_type_for_name("person")
2843 .expect("expected to get a document type");
2844
2845 let too_long_string = "t".repeat(256);
2846 let query_value = json!({
2847 "where": [
2848 ["firstName", "<", too_long_string],
2849 ],
2850 "limit": 100,
2851 "orderBy": [
2852 ["firstName", "asc"],
2853 ["lastName", "asc"],
2854 ],
2855 });
2856
2857 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2858 .expect("expected to serialize to cbor");
2859 let query = DriveDocumentQuery::from_cbor(
2860 where_cbor.as_slice(),
2861 &contract,
2862 document_type,
2863 &DriveConfig::default(),
2864 )
2865 .expect("fields of queries length must be under 256 bytes long");
2866 query
2867 .execute_raw_results_no_proof(&drive, None, None, platform_version)
2868 .expect_err("fields of queries length must be under 256 bytes long");
2869 }
2870
2871 #[test]
2927 fn test_valid_query_timestamp_field_with_null_value() {
2928 let (drive, contract) = setup_family_birthday_contract();
2929
2930 let platform_version = PlatformVersion::latest();
2931
2932 let document_type = contract
2933 .document_type_for_name("person")
2934 .expect("expected to get a document type");
2935
2936 let query_value = json!({
2937 "where": [
2938 ["birthday", ">=", Null],
2939 ],
2940 "limit": 100,
2941 "orderBy": [
2942 ["birthday", "asc"],
2943 ],
2944 });
2945
2946 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2947 .expect("expected to serialize to cbor");
2948 let query = DriveDocumentQuery::from_cbor(
2949 where_cbor.as_slice(),
2950 &contract,
2951 document_type,
2952 &DriveConfig::default(),
2953 )
2954 .expect("The query itself should be valid for a null type");
2955 query
2956 .execute_raw_results_no_proof(&drive, None, None, platform_version)
2957 .expect("a Null value doesn't make sense for a float");
2958 }
2959
2960 #[test]
2961 fn test_invalid_query_in_with_empty_array() {
2962 let (drive, contract) = setup_family_contract();
2963
2964 let platform_version = PlatformVersion::latest();
2965
2966 let document_type = contract
2967 .document_type_for_name("person")
2968 .expect("expected to get a document type");
2969
2970 let query_value = json!({
2971 "where": [
2972 ["firstName", "in", []],
2973 ],
2974 "limit": 100,
2975 "orderBy": [
2976 ["firstName", "asc"],
2977 ],
2978 });
2979
2980 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2981 .expect("expected to serialize to cbor");
2982 let query = DriveDocumentQuery::from_cbor(
2983 where_cbor.as_slice(),
2984 &contract,
2985 document_type,
2986 &DriveConfig::default(),
2987 )
2988 .expect("query should be valid for empty array");
2989
2990 query
2991 .execute_raw_results_no_proof(&drive, None, None, platform_version)
2992 .expect_err("query should not be able to execute for empty array");
2993 }
2994
2995 #[test]
2996 fn test_invalid_query_in_too_many_elements() {
2997 let (drive, contract) = setup_family_contract();
2998
2999 let platform_version = PlatformVersion::latest();
3000
3001 let document_type = contract
3002 .document_type_for_name("person")
3003 .expect("expected to get a document type");
3004
3005 let mut array: Vec<String> = Vec::with_capacity(101);
3006 for _ in 0..array.capacity() {
3007 array.push(String::from("a"));
3008 }
3009 let query_value = json!({
3010 "where": [
3011 ["firstName", "in", array],
3012 ],
3013 "limit": 100,
3014 "orderBy": [
3015 ["firstName", "asc"],
3016 ],
3017 });
3018
3019 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3020 .expect("expected to serialize to cbor");
3021 let query = DriveDocumentQuery::from_cbor(
3022 where_cbor.as_slice(),
3023 &contract,
3024 document_type,
3025 &DriveConfig::default(),
3026 )
3027 .expect("query is valid for too many elements");
3028
3029 query
3030 .execute_raw_results_no_proof(&drive, None, None, platform_version)
3031 .expect_err("query should not be able to execute with too many elements");
3032 }
3033
3034 #[test]
3035 fn test_invalid_query_in_unique_elements() {
3036 let (drive, contract) = setup_family_contract();
3037
3038 let platform_version = PlatformVersion::latest();
3039
3040 let document_type = contract
3041 .document_type_for_name("person")
3042 .expect("expected to get a document type");
3043
3044 let query_value = json!({
3045 "where": [
3046 ["firstName", "in", ["a", "a"]],
3047 ],
3048 "limit": 100,
3049 "orderBy": [
3050 ["firstName", "asc"],
3051 ],
3052 });
3053
3054 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3055 .expect("expected to serialize to cbor");
3056
3057 let query = DriveDocumentQuery::from_cbor(
3061 where_cbor.as_slice(),
3062 &contract,
3063 document_type,
3064 &DriveConfig::default(),
3065 )
3066 .expect("the query should be created");
3067
3068 query
3069 .execute_raw_results_no_proof(&drive, None, None, platform_version)
3070 .expect_err("there should be no duplicates values for In query");
3071 }
3072
3073 #[test]
3074 fn test_invalid_query_starts_with_empty_string() {
3075 let query_value = json!({
3076 "where": [
3077 ["firstName", "startsWith", ""],
3078 ],
3079 "limit": 100,
3080 "orderBy": [
3081 ["firstName", "asc"],
3082 ],
3083 });
3084
3085 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
3086 let document_type = contract
3087 .document_type_for_name("niceDocument")
3088 .expect("expected to get nice document");
3089
3090 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3091 .expect("expected to serialize to cbor");
3092 DriveDocumentQuery::from_cbor(
3093 where_cbor.as_slice(),
3094 &contract,
3095 document_type,
3096 &DriveConfig::default(),
3097 )
3098 .expect_err("starts with can not start with an empty string");
3099 }
3100
3101 #[test]
3102 fn test_invalid_query_limit_too_high() {
3103 let query_value = json!({
3104 "where": [
3105 ["firstName", "startsWith", "a"],
3106 ],
3107 "limit": 101,
3108 "orderBy": [
3109 ["firstName", "asc"],
3110 ],
3111 });
3112
3113 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
3114 let document_type = contract
3115 .document_type_for_name("niceDocument")
3116 .expect("expected to get nice document");
3117
3118 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3119 .expect("expected to serialize to cbor");
3120 DriveDocumentQuery::from_cbor(
3121 where_cbor.as_slice(),
3122 &contract,
3123 document_type,
3124 &DriveConfig::default(),
3125 )
3126 .expect_err("starts with can not start with an empty string");
3127 }
3128
3129 #[test]
3130 fn test_invalid_query_limit_too_low() {
3131 let query_value = json!({
3132 "where": [
3133 ["firstName", "startsWith", "a"],
3134 ],
3135 "limit": -1,
3136 "orderBy": [
3137 ["firstName", "asc"],
3138 ],
3139 });
3140
3141 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
3142 let document_type = contract
3143 .document_type_for_name("niceDocument")
3144 .expect("expected to get nice document");
3145
3146 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3147 .expect("expected to serialize to cbor");
3148 DriveDocumentQuery::from_cbor(
3149 where_cbor.as_slice(),
3150 &contract,
3151 document_type,
3152 &DriveConfig::default(),
3153 )
3154 .expect_err("starts with can not start with an empty string");
3155 }
3156
3157 #[test]
3158 fn test_invalid_query_limit_zero() {
3159 let query_value = json!({
3160 "where": [
3161 ["firstName", "startsWith", "a"],
3162 ],
3163 "limit": 0,
3164 "orderBy": [
3165 ["firstName", "asc"],
3166 ],
3167 });
3168
3169 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
3170 let document_type = contract
3171 .document_type_for_name("niceDocument")
3172 .expect("expected to get nice document");
3173
3174 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3175 .expect("expected to serialize to cbor");
3176 DriveDocumentQuery::from_cbor(
3177 where_cbor.as_slice(),
3178 &contract,
3179 document_type,
3180 &DriveConfig::default(),
3181 )
3182 .expect_err("starts with can not start with an empty string");
3183 }
3184
3185 #[test]
3186 fn test_withdrawal_query_with_missing_transaction_index() {
3187 let (_, contract) = setup_withdrawal_contract();
3189 let platform_version = PlatformVersion::latest();
3190
3191 let document_type_name = "withdrawal";
3192 let document_type = contract
3193 .document_type_for_name(document_type_name)
3194 .expect("expected to get document type");
3195
3196 let drive_document_query = DriveDocumentQuery {
3198 contract: &contract,
3199 document_type,
3200 internal_clauses: InternalClauses {
3201 primary_key_in_clause: None,
3202 primary_key_equal_clause: None,
3203 in_clause: Some(WhereClause {
3204 field: "status".to_string(),
3205 operator: WhereOperator::In,
3206 value: Value::Array(vec![
3207 Value::U64(0),
3208 Value::U64(1),
3209 Value::U64(2),
3210 Value::U64(3),
3211 Value::U64(4),
3212 ]),
3213 }),
3214 range_clause: None,
3215 equal_clauses: BTreeMap::default(),
3216 },
3217 offset: None,
3218 limit: Some(3),
3219 order_by: IndexMap::from([
3220 (
3221 "status".to_string(),
3222 OrderClause {
3223 field: "status".to_string(),
3224 ascending: true,
3225 },
3226 ),
3227 (
3228 "transactionIndex".to_string(),
3229 OrderClause {
3230 field: "transactionIndex".to_string(),
3231 ascending: true,
3232 },
3233 ),
3234 ]),
3235 start_at: Some([3u8; 32]),
3236 start_at_included: false,
3237 block_time_ms: None,
3238 };
3239
3240 let mut properties = BTreeMap::new();
3242 properties.insert("status".to_string(), Value::U64(0));
3243 let starts_at_document = DocumentV0 {
3246 id: Identifier::from([3u8; 32]), owner_id: Identifier::random(),
3248 properties,
3249 revision: None,
3250 created_at: None,
3251 updated_at: None,
3252 transferred_at: None,
3253 created_at_block_height: None,
3254 updated_at_block_height: None,
3255 transferred_at_block_height: None,
3256 created_at_core_block_height: None,
3257 updated_at_core_block_height: None,
3258 transferred_at_core_block_height: None,
3259 creator_id: None,
3260 }
3261 .into();
3262
3263 let result = drive_document_query
3265 .construct_path_query(Some(starts_at_document), platform_version)
3266 .expect("expected to construct a path query");
3267
3268 assert_eq!(
3269 result
3270 .clone()
3271 .query
3272 .query
3273 .default_subquery_branch
3274 .subquery
3275 .expect("expected subquery")
3276 .items,
3277 Query::new_range_full().items
3278 );
3279 }
3280}