1use std::sync::Arc;
2
3#[cfg(any(feature = "server", feature = "verify"))]
4pub use {
5 conditions::{ValueClause, WhereClause, WhereOperator},
6 drive_document_average_query::{AverageEntry, AverageMode},
11 drive_document_count_query::{
18 CountMode, DocumentCountMode, DriveDocumentCountQuery, SplitCountEntry,
19 },
20 drive_document_sum_query::{DriveDocumentSumQuery, SumEntry, SumMode},
25 grovedb::{PathQuery, Query, QueryItem, SizedQuery},
26 having::{
27 HavingAggregate, HavingAggregateFunction, HavingClause, HavingOperator, HavingRanking,
28 HavingRankingKind, HavingRightOperand,
29 },
30 ordering::OrderClause,
31 projection::{SelectFunction, SelectProjection},
32 single_document_drive_query::SingleDocumentDriveQuery,
33 single_document_drive_query::SingleDocumentDriveQueryContestedStatus,
34 vote_polls_by_end_date_query::VotePollsByEndDateDriveQuery,
35 vote_query::IdentityBasedVoteDriveQuery,
36};
37
38#[cfg(feature = "server")]
41pub use drive_document_count_query::{
42 DocumentCountRequest, DocumentCountResponse, RangeCountOptions, MAX_LIMIT_AS_FAILSAFE,
43};
44
45#[cfg(feature = "server")]
49pub use drive_document_sum_query::{DocumentSumRequest, DocumentSumResponse, RangeSumOptions};
50
51#[cfg(feature = "server")]
55pub use drive_document_average_query::{DocumentAverageRequest, DocumentAverageResponse};
56#[cfg(any(feature = "server", feature = "verify"))]
58use {
59 crate::{
60 drive::contract::paths::DataContractPaths,
61 error::{drive::DriveError, query::QuerySyntaxError, Error},
62 },
63 dpp::{
64 data_contract::{
65 accessors::v0::DataContractV0Getters,
66 document_type::{accessors::DocumentTypeV0Getters, methods::DocumentTypeV0Methods},
67 document_type::{DocumentTypeRef, Index, IndexProperty},
68 DataContract,
69 },
70 document::{document_methods::DocumentMethodsV0, Document, DocumentV0Getters},
71 platform_value::{btreemap_extensions::BTreeValueRemoveFromMapHelper, Value},
72 version::PlatformVersion,
73 ProtocolError,
74 },
75 indexmap::IndexMap,
76 sqlparser::{
77 ast::{self, OrderByExpr, Select, Statement, TableFactor::Table, Value::Number},
78 dialect::MySqlDialect,
79 parser::Parser,
80 },
81 std::{collections::BTreeMap, ops::BitXor},
82};
83
84#[cfg(all(feature = "server", feature = "verify"))]
85use crate::verify::RootHash;
86
87#[cfg(feature = "server")]
88use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0;
89#[cfg(feature = "server")]
90pub use grovedb::{
91 query_result_type::{QueryResultElements, QueryResultType},
92 Element, Error as GroveError, TransactionArg,
93};
94
95use dpp::document;
96use dpp::prelude::Identifier;
97use dpp::validation::{SimpleValidationResult, ValidationResult};
98#[cfg(feature = "server")]
99use {
100 crate::{drive::Drive, fees::op::LowLevelDriveOperation},
101 dpp::block::block_info::BlockInfo,
102};
103use crate::config::DriveConfig;
105use crate::util::common::encode::encode_u64;
107#[cfg(feature = "server")]
108use crate::util::grove_operations::QueryType::StatefulQuery;
109
110#[cfg(any(feature = "server", feature = "verify"))]
112pub mod conditions;
113#[cfg(any(feature = "server", feature = "verify"))]
114mod defaults;
115#[cfg(any(feature = "server", feature = "verify"))]
116pub mod having;
117#[cfg(any(feature = "server", feature = "verify"))]
118pub mod ordering;
119#[cfg(any(feature = "server", feature = "verify"))]
120pub mod projection;
121#[cfg(any(feature = "server", feature = "verify"))]
122mod single_document_drive_query;
123
124#[cfg(feature = "server")]
126mod test_index;
127
128#[cfg(any(feature = "server", feature = "verify"))]
129pub mod vote_poll_vote_state_query;
131#[cfg(any(feature = "server", feature = "verify"))]
132pub mod vote_query;
134
135#[cfg(any(feature = "server", feature = "verify"))]
136pub mod vote_poll_contestant_votes_query;
138
139#[cfg(any(feature = "server", feature = "verify"))]
140pub mod vote_polls_by_end_date_query;
142
143#[cfg(any(feature = "server", feature = "verify"))]
144pub mod vote_polls_by_document_type_query;
146
147#[cfg(any(feature = "server", feature = "verify"))]
153pub type ContractLookupFn<'a> =
154 dyn Fn(&Identifier) -> Result<Option<Arc<DataContract>>, Error> + 'a;
155
156#[cfg(any(feature = "server", feature = "verify"))]
167pub fn contract_lookup_fn_for_contract<'a>(
168 data_contract: Arc<DataContract>,
169) -> Box<ContractLookupFn<'a>> {
170 let func = move |id: &Identifier| -> Result<Option<Arc<DataContract>>, Error> {
171 if data_contract.id().ne(id) {
172 return Ok(None);
173 }
174 Ok(Some(Arc::clone(&data_contract)))
175 };
176 Box::new(func)
177}
178
179#[cfg(any(feature = "server", feature = "verify"))]
181pub mod contested_resource_votes_given_by_identity_query;
182#[cfg(any(feature = "server", feature = "verify"))]
184pub mod drive_contested_document_query;
185
186#[cfg(any(feature = "server", feature = "verify"))]
188pub mod proposer_block_count_query;
189
190#[cfg(any(feature = "server", feature = "verify"))]
192pub mod identity_token_balance_drive_query;
193#[cfg(any(feature = "server", feature = "verify"))]
195pub mod identity_token_info_drive_query;
196
197#[cfg(any(feature = "server", feature = "verify"))]
199pub mod filter;
200#[cfg(any(feature = "server", feature = "verify"))]
202pub mod token_status_drive_query;
203
204#[cfg(any(feature = "server", feature = "verify"))]
206pub mod drive_document_count_query;
207
208#[cfg(any(feature = "server", feature = "verify"))]
214pub mod drive_document_sum_query;
215
216#[cfg(any(feature = "server", feature = "verify"))]
223pub mod drive_document_average_query;
224
225#[cfg(feature = "server")]
230pub mod drive_document_count_and_sum_query;
231
232pub type QuerySyntaxValidationResult<TData> = ValidationResult<TData, QuerySyntaxError>;
234
235pub type QuerySyntaxSimpleValidationResult = SimpleValidationResult<QuerySyntaxError>;
237
238#[cfg(any(feature = "server", feature = "verify"))]
239#[derive(Debug, Clone)]
246pub struct StartAtDocument<'a> {
247 pub document: Document,
249
250 pub document_type: DocumentTypeRef<'a>,
252
253 pub included: bool,
257}
258
259#[cfg(any(feature = "server", feature = "verify"))]
261#[derive(Clone, Debug, PartialEq, Default)]
262pub struct InternalClauses {
263 pub primary_key_in_clause: Option<WhereClause>,
265 pub primary_key_equal_clause: Option<WhereClause>,
267 pub in_clause: Option<WhereClause>,
269 pub range_clause: Option<WhereClause>,
271 pub equal_clauses: BTreeMap<String, WhereClause>,
273}
274
275impl InternalClauses {
276 #[cfg(any(feature = "server", feature = "verify"))]
277 pub fn verify(&self) -> bool {
279 if self
281 .primary_key_in_clause
282 .is_some()
283 .bitxor(self.primary_key_equal_clause.is_some())
284 {
285 !(self.in_clause.is_some()
287 || self.range_clause.is_some()
288 || !self.equal_clauses.is_empty())
289 } else {
290 !(self.primary_key_in_clause.is_some() && self.primary_key_equal_clause.is_some())
291 }
292 }
293
294 #[cfg(any(feature = "server", feature = "verify"))]
295 pub fn is_for_primary_key(&self) -> bool {
297 self.primary_key_in_clause.is_some() || self.primary_key_equal_clause.is_some()
298 }
299
300 #[cfg(any(feature = "server", feature = "verify"))]
301 pub fn is_empty(&self) -> bool {
303 self.in_clause.is_none()
304 && self.range_clause.is_none()
305 && self.equal_clauses.is_empty()
306 && self.primary_key_in_clause.is_none()
307 && self.primary_key_equal_clause.is_none()
308 }
309
310 #[cfg(any(feature = "server", feature = "verify"))]
311 pub fn extract_from_clauses(all_where_clauses: Vec<WhereClause>) -> Result<Self, Error> {
313 let primary_key_equal_clauses_array = all_where_clauses
314 .iter()
315 .filter_map(|where_clause| match where_clause.operator {
316 WhereOperator::Equal => match where_clause.is_identifier() {
317 true => Some(where_clause.clone()),
318 false => None,
319 },
320 _ => None,
321 })
322 .collect::<Vec<WhereClause>>();
323
324 let primary_key_in_clauses_array = all_where_clauses
325 .iter()
326 .filter_map(|where_clause| match where_clause.operator {
327 WhereOperator::In => match where_clause.is_identifier() {
328 true => Some(where_clause.clone()),
329 false => None,
330 },
331 _ => None,
332 })
333 .collect::<Vec<WhereClause>>();
334
335 let (equal_clauses, range_clause, in_clause) =
336 WhereClause::group_clauses(&all_where_clauses)?;
337
338 let primary_key_equal_clause = match primary_key_equal_clauses_array.len() {
339 0 => Ok(None),
340 1 => Ok(Some(
341 primary_key_equal_clauses_array
342 .first()
343 .expect("there must be a value")
344 .clone(),
345 )),
346 _ => Err(Error::Query(
347 QuerySyntaxError::DuplicateNonGroupableClauseSameField(
348 "There should only be one equal clause for the primary key",
349 ),
350 )),
351 }?;
352
353 let primary_key_in_clause = match primary_key_in_clauses_array.len() {
354 0 => Ok(None),
355 1 => Ok(Some(
356 primary_key_in_clauses_array
357 .first()
358 .expect("there must be a value")
359 .clone(),
360 )),
361 _ => Err(Error::Query(
362 QuerySyntaxError::DuplicateNonGroupableClauseSameField(
363 "There should only be one in clause for the primary key",
364 ),
365 )),
366 }?;
367
368 let internal_clauses = InternalClauses {
369 primary_key_equal_clause,
370 primary_key_in_clause,
371 in_clause,
372 range_clause,
373 equal_clauses,
374 };
375
376 match internal_clauses.verify() {
377 true => Ok(internal_clauses),
378 false => Err(Error::Query(
379 QuerySyntaxError::InvalidWhereClauseComponents("Query has invalid where clauses"),
380 )),
381 }
382 }
383
384 #[cfg(any(feature = "server", feature = "verify"))]
386 pub fn validate_against_schema(
387 &self,
388 document_type: DocumentTypeRef,
389 ) -> QuerySyntaxSimpleValidationResult {
390 if !self.verify() {
392 return QuerySyntaxSimpleValidationResult::new_with_error(
393 QuerySyntaxError::InvalidWhereClauseComponents(
394 "invalid composition of where clauses",
395 ),
396 );
397 }
398
399 if let Some(in_clause) = &self.in_clause {
401 if in_clause.field == "$id" {
403 return QuerySyntaxSimpleValidationResult::new_with_error(
404 QuerySyntaxError::InvalidWhereClauseComponents(
405 "use primary_key_* clauses for $id",
406 ),
407 );
408 }
409 let result = in_clause.validate_against_schema(document_type);
410 if !result.is_valid() {
411 return result;
412 }
413 }
414
415 if let Some(range_clause) = &self.range_clause {
417 if range_clause.field == "$id" {
419 return QuerySyntaxSimpleValidationResult::new_with_error(
420 QuerySyntaxError::InvalidWhereClauseComponents(
421 "use primary_key_* clauses for $id",
422 ),
423 );
424 }
425 let result = range_clause.validate_against_schema(document_type);
426 if !result.is_valid() {
427 return result;
428 }
429 }
430
431 for (field, eq_clause) in &self.equal_clauses {
433 if field.as_str() == "$id" {
435 return QuerySyntaxSimpleValidationResult::new_with_error(
436 QuerySyntaxError::InvalidWhereClauseComponents(
437 "use primary_key_* clauses for $id",
438 ),
439 );
440 }
441 let result = eq_clause.validate_against_schema(document_type);
442 if !result.is_valid() {
443 return result;
444 }
445 }
446
447 if let Some(pk_eq) = &self.primary_key_equal_clause {
449 if pk_eq.operator != WhereOperator::Equal
450 || !matches!(pk_eq.value, Value::Identifier(_))
451 {
452 return QuerySyntaxSimpleValidationResult::new_with_error(
453 QuerySyntaxError::InvalidWhereClauseComponents(
454 "primary key equality must compare an identifier",
455 ),
456 );
457 }
458 }
459 if let Some(pk_in) = &self.primary_key_in_clause {
460 if pk_in.operator != WhereOperator::In {
461 return QuerySyntaxSimpleValidationResult::new_with_error(
462 QuerySyntaxError::InvalidWhereClauseComponents(
463 "primary key IN must use IN operator",
464 ),
465 );
466 }
467 let result = pk_in.in_values();
469 if !result.is_valid() {
470 return QuerySyntaxSimpleValidationResult::new_with_errors(result.errors);
471 }
472 if let Value::Array(arr) = &pk_in.value {
473 if !arr.iter().all(|v| matches!(v, Value::Identifier(_))) {
474 return QuerySyntaxSimpleValidationResult::new_with_error(
475 QuerySyntaxError::InvalidWhereClauseComponents(
476 "primary key IN must contain identifiers",
477 ),
478 );
479 }
480 } else {
481 return QuerySyntaxSimpleValidationResult::new_with_error(
482 QuerySyntaxError::InvalidWhereClauseComponents(
483 "primary key IN must contain an array of identifiers",
484 ),
485 );
486 }
487 }
488
489 QuerySyntaxSimpleValidationResult::default()
490 }
491}
492
493impl From<InternalClauses> for Vec<WhereClause> {
494 fn from(clauses: InternalClauses) -> Self {
495 let mut result: Self = clauses.equal_clauses.into_values().collect();
496
497 if let Some(clause) = clauses.in_clause {
498 result.push(clause);
499 };
500 if let Some(clause) = clauses.primary_key_equal_clause {
501 result.push(clause);
502 };
503 if let Some(clause) = clauses.primary_key_in_clause {
504 result.push(clause);
505 };
506 if let Some(clause) = clauses.range_clause {
507 result.push(clause);
508 };
509
510 result
511 }
512}
513
514#[cfg(any(feature = "server", feature = "verify"))]
515#[derive(Debug, PartialEq, Clone)]
517pub struct DriveDocumentQuery<'a> {
518 pub contract: &'a DataContract,
520 pub document_type: DocumentTypeRef<'a>,
522 pub internal_clauses: InternalClauses,
524 pub offset: Option<u16>,
526 pub limit: Option<u16>,
528 pub order_by: IndexMap<String, OrderClause>,
530 pub start_at: Option<[u8; 32]>,
532 pub start_at_included: bool,
534 pub block_time_ms: Option<u64>,
536}
537
538impl<'a> DriveDocumentQuery<'a> {
539 #[cfg(any(feature = "server", feature = "verify"))]
541 pub fn new_primary_key_single_item_query(
542 contract: &'a DataContract,
543 document_type: DocumentTypeRef<'a>,
544 id: Identifier,
545 ) -> Self {
546 DriveDocumentQuery {
547 contract,
548 document_type,
549 internal_clauses: InternalClauses {
550 primary_key_in_clause: None,
551 primary_key_equal_clause: Some(WhereClause {
552 field: document::property_names::ID.to_string(),
553 operator: WhereOperator::Equal,
554 value: Value::Identifier(id.to_buffer()),
555 }),
556 in_clause: None,
557 range_clause: None,
558 equal_clauses: Default::default(),
559 },
560 offset: None,
561 limit: None,
562 order_by: Default::default(),
563 start_at: None,
564 start_at_included: false,
565 block_time_ms: None,
566 }
567 }
568
569 #[cfg(feature = "server")]
570 pub fn any_item_query(contract: &'a DataContract, document_type: DocumentTypeRef<'a>) -> Self {
572 DriveDocumentQuery {
573 contract,
574 document_type,
575 internal_clauses: Default::default(),
576 offset: None,
577 limit: Some(1),
578 order_by: Default::default(),
579 start_at: None,
580 start_at_included: true,
581 block_time_ms: None,
582 }
583 }
584
585 #[cfg(feature = "server")]
586 pub fn all_items_query(
588 contract: &'a DataContract,
589 document_type: DocumentTypeRef<'a>,
590 limit: Option<u16>,
591 ) -> Self {
592 DriveDocumentQuery {
593 contract,
594 document_type,
595 internal_clauses: Default::default(),
596 offset: None,
597 limit,
598 order_by: Default::default(),
599 start_at: None,
600 start_at_included: true,
601 block_time_ms: None,
602 }
603 }
604
605 #[cfg(any(feature = "server", feature = "verify"))]
606 pub fn is_for_primary_key(&self) -> bool {
608 self.internal_clauses.is_for_primary_key()
609 || (self.internal_clauses.is_empty()
610 && (self.order_by.is_empty()
611 || (self.order_by.len() == 1
612 && self
613 .order_by
614 .keys()
615 .collect::<Vec<&String>>()
616 .first()
617 .unwrap()
618 .as_str()
619 == "$id")))
620 }
621
622 #[cfg(feature = "cbor_query")]
623 pub fn from_cbor(
625 query_cbor: &[u8],
626 contract: &'a DataContract,
627 document_type: DocumentTypeRef<'a>,
628 config: &DriveConfig,
629 ) -> Result<Self, Error> {
630 let query_document_value: Value = ciborium::de::from_reader(query_cbor).map_err(|_| {
631 Error::Query(QuerySyntaxError::DeserializationError(
632 "unable to decode query from cbor".to_string(),
633 ))
634 })?;
635 Self::from_value(query_document_value, contract, document_type, config)
636 }
637
638 #[cfg(any(feature = "server", feature = "verify"))]
639 pub fn from_value(
641 query_value: Value,
642 contract: &'a DataContract,
643 document_type: DocumentTypeRef<'a>,
644 config: &DriveConfig,
645 ) -> Result<Self, Error> {
646 let query_document: BTreeMap<String, Value> = query_value.into_btree_string_map()?;
647 Self::from_btree_map_value(query_document, contract, document_type, config)
648 }
649
650 #[cfg(any(feature = "server", feature = "verify"))]
651 pub fn from_btree_map_value(
653 mut query_document: BTreeMap<String, Value>,
654 contract: &'a DataContract,
655 document_type: DocumentTypeRef<'a>,
656 config: &DriveConfig,
657 ) -> Result<Self, Error> {
658 if let Some(contract_id) = query_document
659 .remove_optional_identifier("contract_id")
660 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?
661 {
662 if contract.id() != contract_id {
663 return Err(ProtocolError::IdentifierError(format!(
664 "data contract id mismatch, expected: {}, got: {}",
665 contract.id(),
666 contract_id
667 ))
668 .into());
669 };
670 }
671
672 if let Some(document_type_name) = query_document
673 .remove_optional_string("document_type_name")
674 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?
675 {
676 if document_type.name() != &document_type_name {
677 return Err(ProtocolError::IdentifierError(format!(
678 "document type name mismatch, expected: {}, got: {}",
679 document_type.name(),
680 document_type_name
681 ))
682 .into());
683 }
684 }
685
686 let maybe_limit: Option<u16> = query_document
687 .remove_optional_integer("limit")
688 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?;
689
690 let limit = maybe_limit
691 .map_or(Some(config.default_query_limit), |limit_value| {
692 if limit_value == 0 || limit_value > config.default_query_limit {
693 None
694 } else {
695 Some(limit_value)
696 }
697 })
698 .ok_or(Error::Query(QuerySyntaxError::InvalidLimit(format!(
699 "limit greater than max limit {}",
700 config.max_query_limit
701 ))))?;
702
703 let offset: Option<u16> = query_document
704 .remove_optional_integer("offset")
705 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?;
706
707 let block_time_ms: Option<u64> = query_document
708 .remove_optional_integer("blockTime")
709 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))?;
710
711 let all_where_clauses: Vec<WhereClause> =
712 query_document
713 .remove("where")
714 .map_or(Ok(vec![]), |id_cbor| {
715 if let Value::Array(clauses) = id_cbor {
716 clauses
717 .iter()
718 .map(|where_clause| {
719 if let Value::Array(clauses_components) = where_clause {
720 WhereClause::from_components(clauses_components)
721 } else {
722 Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause(
723 "where clause must be an array".to_string(),
724 )))
725 }
726 })
727 .collect::<Result<Vec<WhereClause>, Error>>()
728 } else {
729 Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause(
730 "where clause must be an array".to_string(),
731 )))
732 }
733 })?;
734
735 let internal_clauses = InternalClauses::extract_from_clauses(all_where_clauses)?;
736
737 let start_at_option = query_document.remove("startAt");
738 let start_after_option = query_document.remove("startAfter");
739 if start_after_option.is_some() && start_at_option.is_some() {
740 return Err(Error::Query(QuerySyntaxError::DuplicateStartConditions(
741 "only one of startAt or startAfter should be provided",
742 )));
743 }
744
745 let mut start_at_included = true;
746
747 let mut start_option: Option<Value> = None;
748
749 if start_after_option.is_some() {
750 start_option = start_after_option;
751 start_at_included = false;
752 } else if start_at_option.is_some() {
753 start_option = start_at_option;
754 start_at_included = true;
755 }
756
757 let start_at: Option<[u8; 32]> = start_option
758 .map(|v| {
759 v.into_identifier()
760 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))
761 .map(|identifier| identifier.into_buffer())
762 })
763 .transpose()?;
764
765 let order_by: IndexMap<String, OrderClause> =
766 query_document
767 .remove("orderBy")
768 .map_or(Ok(IndexMap::new()), |id_cbor| {
769 if let Value::Array(clauses) = id_cbor {
770 clauses
771 .into_iter()
772 .filter_map(|order_clause| {
773 if let Value::Array(clauses_components) = order_clause {
774 let order_clause =
775 OrderClause::from_components(&clauses_components)
776 .map_err(Error::from);
777 match order_clause {
778 Ok(order_clause) => {
779 Some(Ok((order_clause.field.clone(), order_clause)))
780 }
781 Err(err) => Some(Err(err)),
782 }
783 } else {
784 None
785 }
786 })
787 .collect::<Result<IndexMap<String, OrderClause>, Error>>()
788 } else {
789 Err(Error::Query(QuerySyntaxError::InvalidOrderByProperties(
790 "order clauses must be an array",
791 )))
792 }
793 })?;
794
795 if !query_document.is_empty() {
796 return Err(Error::Query(QuerySyntaxError::Unsupported(format!(
797 "unsupported syntax in where clause: {:?}",
798 query_document
799 ))));
800 }
801
802 Ok(DriveDocumentQuery {
803 contract,
804 document_type,
805 internal_clauses,
806 limit: Some(limit),
807 offset,
808 order_by,
809 start_at,
810 start_at_included,
811 block_time_ms,
812 })
813 }
814
815 #[cfg(any(feature = "server", feature = "verify"))]
816 #[allow(clippy::too_many_arguments)]
818 pub fn from_decomposed_values(
819 where_clause: Value,
820 order_by: Option<Value>,
821 maybe_limit: Option<u16>,
822 start_at: Option<[u8; 32]>,
823 start_at_included: bool,
824 block_time_ms: Option<u64>,
825 contract: &'a DataContract,
826 document_type: DocumentTypeRef<'a>,
827 config: &DriveConfig,
828 ) -> Result<Self, Error> {
829 let all_where_clauses: Vec<WhereClause> = match where_clause {
830 Value::Null => Ok(vec![]),
831 Value::Array(clauses) => clauses
832 .iter()
833 .map(|where_clause| {
834 if let Value::Array(clauses_components) = where_clause {
835 WhereClause::from_components(clauses_components)
836 } else {
837 Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause(
838 "where clause must be an array".to_string(),
839 )))
840 }
841 })
842 .collect::<Result<Vec<WhereClause>, Error>>(),
843 _ => Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause(
844 "where clause must be an array".to_string(),
845 ))),
846 }?;
847
848 let order_by_clauses: Vec<OrderClause> = match order_by {
856 None | Some(Value::Null) => Vec::new(),
857 Some(Value::Array(clauses)) => clauses
858 .iter()
859 .map(|order_clause| match order_clause {
860 Value::Array(components) => {
861 OrderClause::from_components(components).map_err(|_| {
862 Error::Query(QuerySyntaxError::InvalidOrderByProperties(
863 "invalid order_by clause components",
864 ))
865 })
866 }
867 _ => Err(Error::Query(QuerySyntaxError::InvalidOrderByProperties(
868 "order_by clause must be an array",
869 ))),
870 })
871 .collect::<Result<Vec<_>, _>>()?,
872 Some(_) => {
873 return Err(Error::Query(QuerySyntaxError::InvalidOrderByProperties(
874 "order_by must be an array",
875 )));
876 }
877 };
878
879 Self::from_typed_clauses(
880 all_where_clauses,
881 order_by_clauses,
882 maybe_limit,
883 start_at,
884 start_at_included,
885 block_time_ms,
886 contract,
887 document_type,
888 config,
889 )
890 }
891
892 #[cfg(any(feature = "server", feature = "verify"))]
912 #[allow(clippy::too_many_arguments)]
913 pub fn from_typed_clauses(
914 where_clauses: Vec<WhereClause>,
915 order_by_clauses: Vec<OrderClause>,
916 maybe_limit: Option<u16>,
917 start_at: Option<[u8; 32]>,
918 start_at_included: bool,
919 block_time_ms: Option<u64>,
920 contract: &'a DataContract,
921 document_type: DocumentTypeRef<'a>,
922 config: &DriveConfig,
923 ) -> Result<Self, Error> {
924 let limit = maybe_limit
925 .map_or(Some(config.default_query_limit), |limit_value| {
926 if limit_value == 0 || limit_value > config.default_query_limit {
927 None
928 } else {
929 Some(limit_value)
930 }
931 })
932 .ok_or(Error::Query(QuerySyntaxError::InvalidLimit(format!(
933 "limit greater than max limit {}",
934 config.max_query_limit
935 ))))?;
936
937 let internal_clauses = InternalClauses::extract_from_clauses(where_clauses)?;
938
939 let order_by: IndexMap<String, OrderClause> = order_by_clauses
940 .into_iter()
941 .map(|c| (c.field.clone(), c))
942 .collect();
943
944 Ok(DriveDocumentQuery {
945 contract,
946 document_type,
947 internal_clauses,
948 offset: None,
949 limit: Some(limit),
950 order_by,
951 start_at,
952 start_at_included,
953 block_time_ms,
954 })
955 }
956
957 #[cfg(any(feature = "server", feature = "verify"))]
958 pub fn from_sql_expr(
960 sql_string: &str,
961 contract: &'a DataContract,
962 config: Option<&DriveConfig>,
963 ) -> Result<Self, Error> {
964 let dialect: MySqlDialect = MySqlDialect {};
965 let statements: Vec<Statement> = Parser::parse_sql(&dialect, sql_string)
966 .map_err(|e| Error::Query(QuerySyntaxError::SQLParsingError(e)))?;
967
968 let first_statement =
970 statements
971 .first()
972 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
973 "Issue parsing sql getting first statement".to_string(),
974 )))?;
975
976 let query: &ast::Query = match first_statement {
977 ast::Statement::Query(query_struct) => Some(query_struct),
978 _ => None,
979 }
980 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
981 "Issue parsing sql: not a query".to_string(),
982 )))?;
983
984 let max_limit = config
985 .map(|config| config.max_query_limit)
986 .unwrap_or(DriveConfig::default().max_query_limit);
987
988 let limit: u16 = if let Some(limit_expr) = &query.limit {
989 match limit_expr {
990 ast::Expr::Value(Number(num_string, _)) => {
991 let cast_num_string: &String = num_string;
992 let user_limit = cast_num_string.parse::<u16>().map_err(|e| {
993 Error::Query(QuerySyntaxError::InvalidLimit(format!(
994 "limit could not be parsed {}",
995 e
996 )))
997 })?;
998 if user_limit > max_limit {
999 return Err(Error::Query(QuerySyntaxError::InvalidLimit(format!(
1000 "limit {} greater than max limit {}",
1001 user_limit, max_limit
1002 ))));
1003 }
1004 user_limit
1005 }
1006 result => {
1007 return Err(Error::Query(QuerySyntaxError::InvalidLimit(format!(
1008 "expression not a limit {}",
1009 result
1010 ))));
1011 }
1012 }
1013 } else {
1014 config
1015 .map(|config| config.default_query_limit)
1016 .unwrap_or(DriveConfig::default().default_query_limit)
1017 };
1018
1019 let order_by: IndexMap<String, OrderClause> = query
1020 .order_by
1021 .iter()
1022 .map(|order_exp: &OrderByExpr| {
1023 let ascending = order_exp.asc.is_none() || order_exp.asc.unwrap();
1024 let field = order_exp.expr.to_string();
1025 (field.clone(), OrderClause { field, ascending })
1026 })
1027 .collect::<IndexMap<String, OrderClause>>();
1028
1029 let select: &Select = match &*query.body {
1031 ast::SetExpr::Select(select) => Some(select),
1032 _ => None,
1033 }
1034 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
1035 "Issue parsing sql: Not a select".to_string(),
1036 )))?;
1037
1038 let document_type_name = match &select
1040 .from
1041 .first()
1042 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
1043 "Invalid query: missing from section".to_string(),
1044 )))?
1045 .relation
1046 {
1047 Table { name, .. } => name.0.first().as_ref().map(|identifier| &identifier.value),
1048 _ => None,
1049 }
1050 .ok_or(Error::Query(QuerySyntaxError::InvalidSQL(
1051 "Issue parsing sql: invalid from value".to_string(),
1052 )))?;
1053
1054 let document_type =
1055 contract
1056 .document_types()
1057 .get(document_type_name)
1058 .ok_or(Error::Query(QuerySyntaxError::DocumentTypeNotFound(
1059 "document type not found in contract",
1060 )))?;
1061
1062 let mut all_where_clauses: Vec<WhereClause> = Vec::new();
1072 let selection_tree = select.selection.as_ref();
1073
1074 if let Some(selection_tree) = selection_tree {
1076 WhereClause::build_where_clauses_from_operations(
1077 selection_tree,
1078 document_type,
1079 &mut all_where_clauses,
1080 )?;
1081 }
1082
1083 let internal_clauses = InternalClauses::extract_from_clauses(all_where_clauses)?;
1084
1085 let start_at_option = None; let start_after_option = None; let mut start_at_included = true;
1088 let mut start_option: Option<Value> = None;
1089
1090 if start_after_option.is_some() {
1091 start_option = start_after_option;
1092 start_at_included = false;
1093 } else if start_at_option.is_some() {
1094 start_option = start_at_option;
1095 start_at_included = true;
1096 }
1097
1098 let start_at: Option<[u8; 32]> = start_option
1099 .map(|v| {
1100 v.into_identifier()
1101 .map_err(|e| Error::Protocol(Box::new(ProtocolError::ValueError(e))))
1102 .map(|identifier| identifier.into_buffer())
1103 })
1104 .transpose()?;
1105
1106 Ok(DriveDocumentQuery {
1107 contract,
1108 document_type: document_type.as_ref(),
1109 internal_clauses,
1110 offset: None,
1111 limit: Some(limit),
1112 order_by,
1113 start_at,
1114 start_at_included,
1115 block_time_ms: None,
1116 })
1117 }
1118
1119 #[cfg(feature = "cbor_query")]
1124 pub fn to_cbor(&self) -> Result<Vec<u8>, Error> {
1125 let data: BTreeMap<String, Value> = self.into();
1126 let cbor: BTreeMap<String, ciborium::Value> = Value::convert_to_cbor_map(data)?;
1127 let mut output = Vec::new();
1128
1129 ciborium::ser::into_writer(&cbor, &mut output)
1130 .map_err(|e| ProtocolError::PlatformSerializationError(e.to_string()))?;
1131 Ok(output)
1132 }
1133
1134 #[cfg(any(feature = "server", feature = "verify"))]
1135 pub fn start_at_document_path_and_key(&self, starts_at: &[u8; 32]) -> (Vec<Vec<u8>>, Vec<u8>) {
1137 if self.document_type.documents_keep_history() {
1138 let document_holding_path = self.contract.documents_with_history_primary_key_path(
1139 self.document_type.name().as_str(),
1140 starts_at,
1141 );
1142 (
1143 document_holding_path
1144 .into_iter()
1145 .map(|key| key.to_vec())
1146 .collect::<Vec<_>>(),
1147 vec![0],
1148 )
1149 } else {
1150 let document_holding_path = self
1151 .contract
1152 .documents_primary_key_path(self.document_type.name().as_str());
1153 (
1154 document_holding_path
1155 .into_iter()
1156 .map(|key| key.to_vec())
1157 .collect::<Vec<_>>(),
1158 starts_at.to_vec(),
1159 )
1160 }
1161 }
1162
1163 #[cfg(feature = "server")]
1164 pub fn construct_path_query_operations(
1166 &self,
1167 drive: &Drive,
1168 include_start_at_for_proof: bool,
1169 transaction: TransactionArg,
1170 drive_operations: &mut Vec<LowLevelDriveOperation>,
1171 platform_version: &PlatformVersion,
1172 ) -> Result<PathQuery, Error> {
1173 let drive_version = &platform_version.drive;
1174 let document_type_path = self
1176 .contract
1177 .document_type_path(self.document_type.name().as_str())
1178 .into_iter()
1179 .map(|a| a.to_vec())
1180 .collect::<Vec<Vec<u8>>>();
1181
1182 let (starts_at_document, start_at_path_query) = match &self.start_at {
1183 None => Ok((None, None)),
1184 Some(starts_at) => {
1185 let (start_at_document_path, start_at_document_key) =
1189 self.start_at_document_path_and_key(starts_at);
1190 let start_at_document = drive
1191 .grove_get(
1192 start_at_document_path.as_slice().into(),
1193 &start_at_document_key,
1194 StatefulQuery,
1195 transaction,
1196 drive_operations,
1197 drive_version,
1198 )
1199 .map_err(|e| match e {
1200 Error::GroveDB(e)
1201 if matches!(
1202 e.as_ref(),
1203 GroveError::PathKeyNotFound(_)
1204 | GroveError::PathNotFound(_)
1205 | GroveError::PathParentLayerNotFound(_)
1206 ) =>
1207 {
1208 let error_message = if self.start_at_included {
1209 "startAt document not found"
1210 } else {
1211 "startAfter document not found"
1212 };
1213
1214 Error::Query(QuerySyntaxError::StartDocumentNotFound(error_message))
1215 }
1216 _ => e,
1217 })?
1218 .ok_or(Error::Drive(DriveError::CorruptedCodeExecution(
1219 "expected a value",
1220 )))?;
1221
1222 let path_query =
1223 PathQuery::new_single_key(start_at_document_path, start_at_document_key);
1224
1225 if let Element::Item(item, _) = start_at_document {
1226 let document = Document::from_bytes(
1227 item.as_slice(),
1228 self.document_type,
1229 platform_version,
1230 )?;
1231 Ok((Some((document, self.start_at_included)), Some(path_query)))
1232 } else {
1233 Err(Error::Drive(DriveError::CorruptedDocumentPath(
1234 "Holding paths should only have items",
1235 )))
1236 }
1237 }
1238 }?;
1239 let mut main_path_query = if self.is_for_primary_key() {
1240 self.get_primary_key_path_query(
1241 document_type_path,
1242 starts_at_document,
1243 platform_version,
1244 )
1245 } else {
1246 self.get_non_primary_key_path_query(
1247 document_type_path,
1248 starts_at_document,
1249 platform_version,
1250 )
1251 }?;
1252 if !include_start_at_for_proof {
1253 return Ok(main_path_query);
1254 }
1255
1256 if let Some(start_at_path_query) = start_at_path_query {
1257 let limit = main_path_query.query.limit.take();
1258 let mut merged = PathQuery::merge(
1259 vec![&start_at_path_query, &main_path_query],
1260 &platform_version.drive.grove_version,
1261 )
1262 .map_err(Error::from)?;
1263 merged.query.limit = limit.map(|a| a.saturating_add(1));
1264 Ok(merged)
1265 } else {
1266 Ok(main_path_query)
1267 }
1268 }
1269
1270 #[cfg(any(feature = "server", feature = "verify"))]
1271 pub fn construct_path_query(
1273 &self,
1274 starts_at_document: Option<Document>,
1275 platform_version: &PlatformVersion,
1276 ) -> Result<PathQuery, Error> {
1277 let document_type_path = self
1279 .contract
1280 .document_type_path(self.document_type.name().as_str())
1281 .into_iter()
1282 .map(|a| a.to_vec())
1283 .collect::<Vec<Vec<u8>>>();
1284 let starts_at_document = starts_at_document
1285 .map(|starts_at_document| (starts_at_document, self.start_at_included));
1286 if self.is_for_primary_key() {
1287 self.get_primary_key_path_query(
1288 document_type_path,
1289 starts_at_document,
1290 platform_version,
1291 )
1292 } else {
1293 self.get_non_primary_key_path_query(
1294 document_type_path,
1295 starts_at_document,
1296 platform_version,
1297 )
1298 }
1299 }
1300
1301 #[cfg(any(feature = "server", feature = "verify"))]
1302 pub fn get_primary_key_path_query(
1304 &self,
1305 document_type_path: Vec<Vec<u8>>,
1306 starts_at_document: Option<(Document, bool)>,
1307 platform_version: &PlatformVersion,
1308 ) -> Result<PathQuery, Error> {
1309 let mut path = document_type_path;
1310
1311 path.push(vec![0]);
1313
1314 if let Some(primary_key_equal_clause) = &self.internal_clauses.primary_key_equal_clause {
1315 let mut query = Query::new();
1316 let key = self.document_type.serialize_value_for_key(
1317 "$id",
1318 &primary_key_equal_clause.value,
1319 platform_version,
1320 )?;
1321 query.insert_key(key);
1322
1323 if self.document_type.documents_keep_history() {
1324 if let Some(block_time) = self.block_time_ms {
1326 let encoded_block_time = encode_u64(block_time);
1327 let mut sub_query = Query::new_with_direction(false);
1328 sub_query.insert_range_to_inclusive(..=encoded_block_time);
1329 query.set_subquery(sub_query);
1330 } else {
1331 query.set_subquery_key(vec![0]);
1332 }
1333 }
1334
1335 Ok(PathQuery::new(path, SizedQuery::new(query, Some(1), None)))
1336 } else {
1337 let left_to_right = if self.order_by.keys().len() == 1 {
1339 if self.order_by.keys().next().unwrap() != "$id" {
1340 return Err(Error::Query(QuerySyntaxError::InvalidOrderByProperties(
1341 "order by should include $id only",
1342 )));
1343 }
1344
1345 let order_clause = self.order_by.get("$id").unwrap();
1346
1347 order_clause.ascending
1348 } else {
1349 true
1350 };
1351
1352 let mut query = Query::new_with_direction(left_to_right);
1353 let starts_at_key_option = match starts_at_document {
1356 None => None,
1357 Some((document, included)) => {
1358 document
1360 .get_raw_for_document_type(
1361 "$id",
1362 self.document_type,
1363 None,
1364 platform_version,
1365 )?
1366 .map(|raw_value_option| (raw_value_option, included))
1367 }
1368 };
1369
1370 if let Some(primary_key_in_clause) = &self.internal_clauses.primary_key_in_clause {
1371 let in_values = primary_key_in_clause.in_values().into_data_with_error()??;
1372
1373 match starts_at_key_option {
1374 None => {
1375 for value in in_values.iter() {
1376 let key = self.document_type.serialize_value_for_key(
1377 "$id",
1378 value,
1379 platform_version,
1380 )?;
1381 query.insert_key(key)
1382 }
1383 }
1384 Some((starts_at_key, included)) => {
1385 for value in in_values.iter() {
1386 let key = self.document_type.serialize_value_for_key(
1387 "$id",
1388 value,
1389 platform_version,
1390 )?;
1391
1392 if (left_to_right && starts_at_key < key)
1393 || (!left_to_right && starts_at_key > key)
1394 || (included && starts_at_key == key)
1395 {
1396 query.insert_key(key);
1397 }
1398 }
1399 }
1400 }
1401
1402 if self.document_type.documents_keep_history() {
1403 if let Some(_block_time) = self.block_time_ms {
1405 return Err(Error::Query(QuerySyntaxError::Unsupported(
1407 "Not yet implemented".to_string(),
1408 )));
1409 } else {
1417 query.set_subquery_key(vec![0]);
1418 }
1419 }
1420
1421 Ok(PathQuery::new(
1422 path,
1423 SizedQuery::new(query, self.limit, self.offset),
1424 ))
1425 } else {
1426 match starts_at_key_option {
1428 None => {
1429 query.insert_all();
1430 }
1431 Some((starts_at_key, included)) => match left_to_right {
1432 true => match included {
1433 true => query.insert_range_from(starts_at_key..),
1434 false => query.insert_range_after(starts_at_key..),
1435 },
1436 false => match included {
1437 true => query.insert_range_to_inclusive(..=starts_at_key),
1438 false => query.insert_range_to(..starts_at_key),
1439 },
1440 },
1441 }
1442
1443 if self.document_type.documents_keep_history() {
1444 if let Some(_block_time) = self.block_time_ms {
1446 return Err(Error::Query(QuerySyntaxError::Unsupported(
1447 "this query is not supported".to_string(),
1448 )));
1449 } else {
1457 query.set_subquery_key(vec![0]);
1458 }
1459 }
1460
1461 Ok(PathQuery::new(
1462 path,
1463 SizedQuery::new(query, self.limit, self.offset),
1464 ))
1465 }
1466 }
1467 }
1468
1469 #[cfg(any(feature = "server", feature = "verify"))]
1470 pub fn find_best_index(&self, platform_version: &PlatformVersion) -> Result<&Index, Error> {
1472 let equal_fields = self
1473 .internal_clauses
1474 .equal_clauses
1475 .keys()
1476 .map(|s| s.as_str())
1477 .collect::<Vec<&str>>();
1478 let in_field = self
1479 .internal_clauses
1480 .in_clause
1481 .as_ref()
1482 .map(|in_clause| in_clause.field.as_str());
1483 let range_field = self
1484 .internal_clauses
1485 .range_clause
1486 .as_ref()
1487 .map(|range_clause| range_clause.field.as_str());
1488 let mut fields = equal_fields;
1489 if let Some(range_field) = range_field {
1490 fields.push(range_field);
1491 }
1492 if let Some(in_field) = in_field {
1493 fields.push(in_field);
1494 }
1496
1497 let order_by_keys: Vec<&str> = self
1498 .order_by
1499 .keys()
1500 .map(|key: &String| {
1501 let str = key.as_str();
1502 if !fields.contains(&str) {
1503 fields.push(str);
1504 }
1505 str
1506 })
1507 .collect();
1508
1509 let (index, difference) = self
1510 .document_type
1511 .index_for_types(
1512 fields.as_slice(),
1513 in_field,
1514 order_by_keys.as_slice(),
1515 platform_version,
1516 )?
1517 .ok_or(Error::Query(
1518 QuerySyntaxError::WhereClauseOnNonIndexedProperty(format!(
1519 "query must be for valid indexes, valid indexes are: {:?}",
1520 self.document_type.indexes()
1521 )),
1522 ))?;
1523 if difference > defaults::MAX_INDEX_DIFFERENCE {
1524 return Err(Error::Query(QuerySyntaxError::QueryTooFarFromIndex(
1525 "query must better match an existing index",
1526 )));
1527 }
1528 Ok(index)
1529 }
1530
1531 #[cfg(any(feature = "server", feature = "verify"))]
1532 pub fn query_item_for_starts_at_key(starts_at_key: Vec<u8>, left_to_right: bool) -> QueryItem {
1534 if left_to_right {
1535 QueryItem::RangeAfter(starts_at_key..)
1536 } else {
1537 QueryItem::RangeTo(..starts_at_key)
1538 }
1539 }
1540
1541 #[cfg(any(feature = "server", feature = "verify"))]
1542 fn inner_query_from_starts_at_for_id(
1544 starts_at_document: Option<&StartAtDocument>,
1545 left_to_right: bool,
1546 ) -> Query {
1547 let mut inner_query = Query::new_with_direction(left_to_right);
1549
1550 if let Some(StartAtDocument {
1551 document, included, ..
1552 }) = starts_at_document
1553 {
1554 let start_at_key = document.id().to_vec();
1555 if *included {
1556 inner_query.insert_range_from(start_at_key..)
1557 } else {
1558 inner_query.insert_range_after(start_at_key..)
1559 }
1560 } else {
1561 inner_query.insert_all();
1563 }
1564 inner_query
1565 }
1566
1567 #[cfg(any(feature = "server", feature = "verify"))]
1568 fn inner_query_starts_from_key(
1570 start_at_key: Option<Vec<u8>>,
1571 left_to_right: bool,
1572 included: bool,
1573 ) -> Query {
1574 let mut inner_query = Query::new_with_direction(left_to_right);
1576
1577 if left_to_right {
1578 if let Some(start_at_key) = start_at_key {
1579 if included {
1580 inner_query.insert_range_from(start_at_key..);
1581 } else {
1582 inner_query.insert_range_after(start_at_key..);
1583 }
1584 } else {
1585 inner_query.insert_all();
1586 }
1587 } else if included {
1588 if let Some(start_at_key) = start_at_key {
1589 inner_query.insert_range_to_inclusive(..=start_at_key);
1590 } else {
1591 inner_query.insert_key(vec![]);
1592 }
1593 } else if let Some(start_at_key) = start_at_key {
1594 inner_query.insert_range_to(..start_at_key);
1595 } else {
1596 inner_query.insert_key(vec![]);
1599 }
1600
1601 inner_query
1602 }
1603
1604 #[cfg(any(feature = "server", feature = "verify"))]
1605 fn inner_query_from_starts_at(
1607 starts_at_document: Option<&StartAtDocument>,
1608 indexed_property: &IndexProperty,
1609 left_to_right: bool,
1610 platform_version: &PlatformVersion,
1611 ) -> Result<Query, Error> {
1612 let mut inner_query = Query::new_with_direction(left_to_right);
1613 if let Some(StartAtDocument {
1614 document,
1615 document_type,
1616 included,
1617 }) = starts_at_document
1618 {
1619 let start_at_key = document.get_raw_for_document_type(
1621 indexed_property.name.as_str(),
1622 *document_type,
1623 None,
1624 platform_version,
1625 )?;
1626 if let Some(start_at_key) = start_at_key {
1628 if left_to_right {
1629 if *included {
1630 inner_query.insert_range_from(start_at_key..)
1631 } else {
1632 inner_query.insert_range_after(start_at_key..)
1633 }
1634 } else if *included {
1635 inner_query.insert_range_to_inclusive(..=start_at_key)
1636 } else {
1637 inner_query.insert_range_to(..start_at_key)
1638 }
1639 } else if left_to_right {
1640 inner_query.insert_all();
1641 } else {
1642 inner_query.insert_key(vec![]);
1643 }
1644 } else {
1645 inner_query.insert_all();
1647 }
1648 Ok(inner_query)
1649 }
1650
1651 #[cfg(any(feature = "server", feature = "verify"))]
1652 fn recursive_create_query(
1653 left_over_index_properties: &[&IndexProperty],
1654 unique: bool,
1655 starts_at_document: Option<&StartAtDocument>, indexed_property: &IndexProperty,
1657 order_by: Option<&IndexMap<String, OrderClause>>,
1658 platform_version: &PlatformVersion,
1659 ) -> Result<Option<Query>, Error> {
1660 match left_over_index_properties.split_first() {
1661 None => Ok(None),
1662 Some((first, left_over)) => {
1663 let left_to_right = if let Some(order_by) = order_by {
1664 order_by
1665 .get(first.name.as_str())
1666 .map(|order_clause| order_clause.ascending)
1667 .unwrap_or(first.ascending)
1668 } else {
1669 first.ascending
1670 };
1671
1672 let mut inner_query = Self::inner_query_from_starts_at(
1673 starts_at_document,
1674 indexed_property,
1675 left_to_right,
1676 platform_version,
1677 )?;
1678 DriveDocumentQuery::recursive_insert_on_query(
1679 &mut inner_query,
1680 left_over,
1681 unique,
1682 starts_at_document,
1683 left_to_right,
1684 order_by,
1685 platform_version,
1686 )?;
1687 Ok(Some(inner_query))
1688 }
1689 }
1690 }
1691
1692 #[cfg(any(feature = "server", feature = "verify"))]
1693 fn recursive_insert_on_query(
1774 query: &mut Query,
1775 left_over_index_properties: &[&IndexProperty],
1776 unique: bool,
1777 starts_at_document: Option<&StartAtDocument>, default_left_to_right: bool,
1779 order_by: Option<&IndexMap<String, OrderClause>>,
1780 platform_version: &PlatformVersion,
1781 ) -> Result<Option<Query>, Error> {
1782 match left_over_index_properties.split_first() {
1783 None => {
1784 match unique {
1785 true => {
1786 query.set_subquery_key(vec![0]);
1787
1788 let inner_query = Self::inner_query_from_starts_at_for_id(
1790 starts_at_document,
1791 true, );
1793 query.add_conditional_subquery(
1794 QueryItem::Key(b"".to_vec()),
1795 Some(vec![vec![0]]),
1796 Some(inner_query),
1797 );
1798 }
1799 false => {
1800 query.set_subquery_key(vec![0]);
1801 let full_query =
1803 Self::inner_query_from_starts_at_for_id(None, default_left_to_right);
1804 query.set_subquery(full_query);
1805
1806 let inner_query = Self::inner_query_from_starts_at_for_id(
1807 starts_at_document,
1808 default_left_to_right,
1809 );
1810
1811 query.add_conditional_subquery(
1812 QueryItem::Key(b"".to_vec()),
1813 Some(vec![vec![0]]),
1814 Some(inner_query),
1815 );
1816 }
1817 }
1818 Ok(None)
1819 }
1820 Some((first, left_over)) => {
1821 let left_to_right = if let Some(order_by) = order_by {
1822 order_by
1823 .get(first.name.as_str())
1824 .map(|order_clause| order_clause.ascending)
1825 .unwrap_or(first.ascending)
1826 } else {
1827 first.ascending
1828 };
1829
1830 if let Some(start_at_document_inner) = starts_at_document {
1831 let StartAtDocument {
1832 document,
1833 document_type,
1834 included,
1835 } = start_at_document_inner;
1836 let start_at_key = document
1837 .get_raw_for_document_type(
1838 first.name.as_str(),
1839 *document_type,
1840 None,
1841 platform_version,
1842 )
1843 .ok()
1844 .flatten();
1845
1846 let non_conditional_included =
1848 !left_over.is_empty() || *included || start_at_key.is_none();
1849
1850 let mut non_conditional_query = Self::inner_query_starts_from_key(
1851 start_at_key.clone(),
1852 left_to_right,
1853 non_conditional_included,
1854 );
1855
1856 DriveDocumentQuery::recursive_insert_on_query(
1901 &mut non_conditional_query,
1902 left_over,
1903 unique,
1904 None,
1905 left_to_right,
1906 order_by,
1907 platform_version,
1908 )?;
1909
1910 DriveDocumentQuery::recursive_conditional_insert_on_query(
1911 &mut non_conditional_query,
1912 start_at_key,
1913 left_over,
1914 unique,
1915 start_at_document_inner,
1916 left_to_right,
1917 order_by,
1918 platform_version,
1919 )?;
1920
1921 query.set_subquery(non_conditional_query);
1922 } else {
1923 let mut inner_query = Query::new_with_direction(first.ascending);
1924 inner_query.insert_all();
1925 DriveDocumentQuery::recursive_insert_on_query(
1926 &mut inner_query,
1927 left_over,
1928 unique,
1929 starts_at_document,
1930 left_to_right,
1931 order_by,
1932 platform_version,
1933 )?;
1934 query.set_subquery(inner_query);
1935 }
1936 query.set_subquery_key(first.name.as_bytes().to_vec());
1937 Ok(None)
1938 }
1939 }
1940 }
1941
1942 #[cfg(any(feature = "server", feature = "verify"))]
1943 #[allow(clippy::too_many_arguments)]
1944 fn recursive_conditional_insert_on_query(
1945 query: &mut Query,
1946 conditional_value: Option<Vec<u8>>,
1947 left_over_index_properties: &[&IndexProperty],
1948 unique: bool,
1949 starts_at_document: &StartAtDocument,
1950 default_left_to_right: bool,
1951 order_by: Option<&IndexMap<String, OrderClause>>,
1952 platform_version: &PlatformVersion,
1953 ) -> Result<(), Error> {
1954 match left_over_index_properties.split_first() {
1955 None => {
1956 match unique {
1957 true => {
1958 let inner_query = Self::inner_query_from_starts_at_for_id(
1960 Some(starts_at_document),
1961 true, );
1963 query.add_conditional_subquery(
1964 QueryItem::Key(b"".to_vec()),
1965 Some(vec![vec![0]]),
1966 Some(inner_query),
1967 );
1968 }
1969 false => {
1970 let inner_query = Self::inner_query_from_starts_at_for_id(
1971 Some(starts_at_document),
1972 default_left_to_right,
1973 );
1974
1975 query.add_conditional_subquery(
1976 QueryItem::Key(conditional_value.unwrap_or_default()),
1977 Some(vec![vec![0]]),
1978 Some(inner_query),
1979 );
1980 }
1981 }
1982 }
1983 Some((first, left_over)) => {
1984 let left_to_right = if let Some(order_by) = order_by {
1985 order_by
1986 .get(first.name.as_str())
1987 .map(|order_clause| order_clause.ascending)
1988 .unwrap_or(first.ascending)
1989 } else {
1990 first.ascending
1991 };
1992
1993 let StartAtDocument {
1994 document,
1995 document_type,
1996 ..
1997 } = starts_at_document;
1998
1999 let lower_start_at_key = document
2000 .get_raw_for_document_type(
2001 first.name.as_str(),
2002 *document_type,
2003 None,
2004 platform_version,
2005 )
2006 .ok()
2007 .flatten();
2008
2009 let non_conditional_included = !unique || lower_start_at_key.is_none();
2012
2013 let mut non_conditional_query = Self::inner_query_starts_from_key(
2014 lower_start_at_key.clone(),
2015 left_to_right,
2016 non_conditional_included,
2017 );
2018
2019 DriveDocumentQuery::recursive_insert_on_query(
2020 &mut non_conditional_query,
2021 left_over,
2022 unique,
2023 None,
2024 left_to_right,
2025 order_by,
2026 platform_version,
2027 )?;
2028
2029 DriveDocumentQuery::recursive_conditional_insert_on_query(
2030 &mut non_conditional_query,
2031 lower_start_at_key,
2032 left_over,
2033 unique,
2034 starts_at_document,
2035 left_to_right,
2036 order_by,
2037 platform_version,
2038 )?;
2039
2040 query.add_conditional_subquery(
2041 QueryItem::Key(conditional_value.unwrap_or_default()),
2042 Some(vec![first.name.as_bytes().to_vec()]),
2043 Some(non_conditional_query),
2044 );
2045 }
2046 }
2047 Ok(())
2048 }
2049
2050 #[cfg(any(feature = "server", feature = "verify"))]
2051 pub fn get_non_primary_key_path_query(
2053 &self,
2054 document_type_path: Vec<Vec<u8>>,
2055 starts_at_document: Option<(Document, bool)>,
2056 platform_version: &PlatformVersion,
2057 ) -> Result<PathQuery, Error> {
2058 let index = self.find_best_index(platform_version)?;
2059 let ordered_clauses: Vec<&WhereClause> = index
2060 .properties
2061 .iter()
2062 .filter_map(|field| self.internal_clauses.equal_clauses.get(field.name.as_str()))
2063 .collect();
2064 let (last_clause, last_clause_is_range, subquery_clause) = match &self
2065 .internal_clauses
2066 .in_clause
2067 {
2068 None => match &self.internal_clauses.range_clause {
2069 None => (ordered_clauses.last().copied(), false, None),
2070 Some(where_clause) => (Some(where_clause), true, None),
2071 },
2072 Some(in_clause) => match &self.internal_clauses.range_clause {
2073 None => (Some(in_clause), true, None),
2074 Some(range_clause) => {
2075 let position_of = |field: &str| -> Option<usize> {
2086 index
2087 .properties
2088 .iter()
2089 .position(|p| p.name.as_str() == field)
2090 };
2091 let in_pos = position_of(in_clause.field.as_str());
2092 let range_pos = position_of(range_clause.field.as_str());
2093 match (in_pos, range_pos) {
2094 (Some(i), Some(r)) if i > r => (Some(range_clause), true, Some(in_clause)),
2095 _ => (Some(in_clause), true, Some(range_clause)),
2096 }
2097 }
2098 },
2099 };
2100
2101 let left_over_index_properties = index
2103 .properties
2104 .iter()
2105 .filter(|field| {
2106 !(self
2107 .internal_clauses
2108 .equal_clauses
2109 .contains_key(field.name.as_str())
2110 || (last_clause.is_some() && last_clause.unwrap().field == field.name)
2111 || (subquery_clause.is_some() && subquery_clause.unwrap().field == field.name))
2112 })
2113 .collect::<Vec<&IndexProperty>>();
2114
2115 let intermediate_values = index
2116 .properties
2117 .iter()
2118 .filter_map(|field| {
2119 match self.internal_clauses.equal_clauses.get(field.name.as_str()) {
2120 None => None,
2121 Some(where_clause) => {
2122 if !last_clause_is_range
2123 && last_clause.is_some()
2124 && last_clause.unwrap().field == field.name
2125 {
2126 None
2128 } else {
2129 Some(self.document_type.serialize_value_for_key(
2130 field.name.as_str(),
2131 &where_clause.value,
2132 platform_version,
2133 ))
2134 }
2135 }
2136 }
2137 })
2138 .collect::<Result<Vec<Vec<u8>>, ProtocolError>>()
2139 .map_err(Error::from)?;
2140
2141 let final_query = match last_clause {
2142 None => {
2143 let first_index = index.properties.first().ok_or(Error::Drive(
2146 DriveError::CorruptedContractIndexes("index must have properties".to_string()),
2147 ))?; Self::recursive_create_query(
2149 left_over_index_properties.as_slice(),
2150 index.unique,
2151 starts_at_document
2152 .map(|(document, included)| StartAtDocument {
2153 document,
2154 document_type: self.document_type,
2155 included,
2156 })
2157 .as_ref(),
2158 first_index,
2159 Some(&self.order_by),
2160 platform_version,
2161 )?
2162 .expect("Index must have left over properties if no last clause")
2163 }
2164 Some(where_clause) => {
2165 let left_to_right = if where_clause.operator.is_range() {
2166 let order_clause: &OrderClause = self
2167 .order_by
2168 .get(where_clause.field.as_str())
2169 .ok_or(Error::Query(QuerySyntaxError::MissingOrderByForRange(
2170 "query must have an orderBy field for each range element",
2171 )))?;
2172
2173 order_clause.ascending
2174 } else {
2175 true
2176 };
2177
2178 let query_starts_at_document = if left_over_index_properties.is_empty() {
2182 &starts_at_document
2183 } else {
2184 &None
2185 };
2186
2187 let mut query = where_clause.to_path_query(
2188 self.document_type,
2189 query_starts_at_document,
2190 left_to_right,
2191 platform_version,
2192 )?;
2193
2194 match subquery_clause {
2195 None => {
2196 Self::recursive_insert_on_query(
2197 &mut query,
2198 left_over_index_properties.as_slice(),
2199 index.unique,
2200 starts_at_document
2201 .map(|(document, included)| StartAtDocument {
2202 document,
2203 document_type: self.document_type,
2204 included,
2205 })
2206 .as_ref(),
2207 left_to_right,
2208 Some(&self.order_by),
2209 platform_version,
2210 )?;
2211 }
2212 Some(subquery_where_clause) => {
2213 let order_clause: &OrderClause = self
2214 .order_by
2215 .get(subquery_where_clause.field.as_str())
2216 .ok_or(Error::Query(QuerySyntaxError::MissingOrderByForRange(
2217 "query must have an orderBy field for each range element",
2218 )))?;
2219 let mut subquery = subquery_where_clause.to_path_query(
2220 self.document_type,
2221 &starts_at_document,
2222 order_clause.ascending,
2223 platform_version,
2224 )?;
2225 Self::recursive_insert_on_query(
2226 &mut subquery,
2227 left_over_index_properties.as_slice(),
2228 index.unique,
2229 starts_at_document
2230 .map(|(document, included)| StartAtDocument {
2231 document,
2232 document_type: self.document_type,
2233 included,
2234 })
2235 .as_ref(),
2236 left_to_right,
2237 Some(&self.order_by),
2238 platform_version,
2239 )?;
2240 let subindex = subquery_where_clause.field.as_bytes().to_vec();
2241 query.set_subquery_key(subindex);
2242 query.set_subquery(subquery);
2243 }
2244 };
2245
2246 query
2247 }
2248 };
2249
2250 let (intermediate_indexes, last_indexes) =
2251 index.properties.split_at(intermediate_values.len());
2252
2253 let last_index = last_indexes.first().ok_or(Error::Query(
2255 QuerySyntaxError::QueryOnDocumentTypeWithNoIndexes(
2256 "document query has no index with fields",
2257 ),
2258 ))?;
2259
2260 let mut path = document_type_path;
2261
2262 for (intermediate_index, intermediate_value) in
2263 intermediate_indexes.iter().zip(intermediate_values.iter())
2264 {
2265 path.push(intermediate_index.name.as_bytes().to_vec());
2266 path.push(intermediate_value.as_slice().to_vec());
2267 }
2268
2269 path.push(last_index.name.as_bytes().to_vec());
2270
2271 Ok(PathQuery::new(
2272 path,
2273 SizedQuery::new(final_query, self.limit, self.offset),
2274 ))
2275 }
2276
2277 #[cfg(feature = "server")]
2278 pub fn execute_with_proof(
2280 self,
2281 drive: &Drive,
2282 block_info: Option<BlockInfo>,
2283 transaction: TransactionArg,
2284 platform_version: &PlatformVersion,
2285 ) -> Result<(Vec<u8>, u64), Error> {
2286 let mut drive_operations = vec![];
2287 let items = self.execute_with_proof_internal(
2288 drive,
2289 transaction,
2290 &mut drive_operations,
2291 platform_version,
2292 )?;
2293 let cost = if let Some(block_info) = block_info {
2294 let fee_result = Drive::calculate_fee(
2295 None,
2296 Some(drive_operations),
2297 &block_info.epoch,
2298 drive.config.epochs_per_era,
2299 platform_version,
2300 None,
2301 )?;
2302 fee_result.processing_fee
2303 } else {
2304 0
2305 };
2306 Ok((items, cost))
2307 }
2308
2309 #[cfg(feature = "server")]
2310 pub(crate) fn execute_with_proof_internal(
2312 self,
2313 drive: &Drive,
2314 transaction: TransactionArg,
2315 drive_operations: &mut Vec<LowLevelDriveOperation>,
2316 platform_version: &PlatformVersion,
2317 ) -> Result<Vec<u8>, Error> {
2318 let path_query = self.construct_path_query_operations(
2319 drive,
2320 true,
2321 transaction,
2322 drive_operations,
2323 platform_version,
2324 )?;
2325 drive.grove_get_proved_path_query(
2326 &path_query,
2327 transaction,
2328 drive_operations,
2329 &platform_version.drive,
2330 )
2331 }
2332
2333 #[cfg(all(feature = "server", feature = "verify"))]
2334 pub fn execute_with_proof_only_get_elements(
2336 self,
2337 drive: &Drive,
2338 block_info: Option<BlockInfo>,
2339 transaction: TransactionArg,
2340 platform_version: &PlatformVersion,
2341 ) -> Result<(RootHash, Vec<Vec<u8>>, u64), Error> {
2342 let mut drive_operations = vec![];
2343 let (root_hash, items) = self.execute_with_proof_only_get_elements_internal(
2344 drive,
2345 transaction,
2346 &mut drive_operations,
2347 platform_version,
2348 )?;
2349 let cost = if let Some(block_info) = block_info {
2350 let fee_result = Drive::calculate_fee(
2351 None,
2352 Some(drive_operations),
2353 &block_info.epoch,
2354 drive.config.epochs_per_era,
2355 platform_version,
2356 None,
2357 )?;
2358 fee_result.processing_fee
2359 } else {
2360 0
2361 };
2362 Ok((root_hash, items, cost))
2363 }
2364
2365 #[cfg(all(feature = "server", feature = "verify"))]
2366 pub(crate) fn execute_with_proof_only_get_elements_internal(
2368 self,
2369 drive: &Drive,
2370 transaction: TransactionArg,
2371 drive_operations: &mut Vec<LowLevelDriveOperation>,
2372 platform_version: &PlatformVersion,
2373 ) -> Result<(RootHash, Vec<Vec<u8>>), Error> {
2374 let path_query = self.construct_path_query_operations(
2375 drive,
2376 true,
2377 transaction,
2378 drive_operations,
2379 platform_version,
2380 )?;
2381
2382 let proof = drive.grove_get_proved_path_query(
2383 &path_query,
2384 transaction,
2385 drive_operations,
2386 &platform_version.drive,
2387 )?;
2388 self.verify_proof_keep_serialized(proof.as_slice(), platform_version)
2389 }
2390
2391 #[cfg(feature = "server")]
2392 pub fn execute_raw_results_no_proof(
2394 &self,
2395 drive: &Drive,
2396 block_info: Option<BlockInfo>,
2397 transaction: TransactionArg,
2398 platform_version: &PlatformVersion,
2399 ) -> Result<(Vec<Vec<u8>>, u16, u64), Error> {
2400 let mut drive_operations = vec![];
2401 let (items, skipped) = self.execute_raw_results_no_proof_internal(
2402 drive,
2403 transaction,
2404 &mut drive_operations,
2405 platform_version,
2406 )?;
2407 let cost = if let Some(block_info) = block_info {
2408 let fee_result = Drive::calculate_fee(
2409 None,
2410 Some(drive_operations),
2411 &block_info.epoch,
2412 drive.config.epochs_per_era,
2413 platform_version,
2414 None,
2415 )?;
2416 fee_result.processing_fee
2417 } else {
2418 0
2419 };
2420 Ok((items, skipped, cost))
2421 }
2422
2423 #[cfg(feature = "server")]
2424 pub(crate) fn execute_raw_results_no_proof_internal(
2426 &self,
2427 drive: &Drive,
2428 transaction: TransactionArg,
2429 drive_operations: &mut Vec<LowLevelDriveOperation>,
2430 platform_version: &PlatformVersion,
2431 ) -> Result<(Vec<Vec<u8>>, u16), Error> {
2432 let path_query = self.construct_path_query_operations(
2433 drive,
2434 false,
2435 transaction,
2436 drive_operations,
2437 platform_version,
2438 )?;
2439
2440 let query_result = drive.grove_get_path_query_serialized_results(
2441 &path_query,
2442 transaction,
2443 drive_operations,
2444 &platform_version.drive,
2445 );
2446 match query_result {
2447 Err(Error::GroveDB(e))
2448 if matches!(
2449 e.as_ref(),
2450 GroveError::PathKeyNotFound(_)
2451 | GroveError::PathNotFound(_)
2452 | GroveError::PathParentLayerNotFound(_)
2453 ) =>
2454 {
2455 Ok((Vec::new(), 0))
2456 }
2457 _ => {
2458 let (data, skipped) = query_result?;
2459 {
2460 Ok((data, skipped))
2461 }
2462 }
2463 }
2464 }
2465
2466 #[cfg(feature = "server")]
2467 pub(crate) fn execute_no_proof_internal(
2469 &self,
2470 drive: &Drive,
2471 result_type: QueryResultType,
2472 transaction: TransactionArg,
2473 drive_operations: &mut Vec<LowLevelDriveOperation>,
2474 platform_version: &PlatformVersion,
2475 ) -> Result<(QueryResultElements, u16), Error> {
2476 let path_query = self.construct_path_query_operations(
2477 drive,
2478 false,
2479 transaction,
2480 drive_operations,
2481 platform_version,
2482 )?;
2483 let query_result = drive.grove_get_path_query(
2484 &path_query,
2485 transaction,
2486 result_type,
2487 drive_operations,
2488 &platform_version.drive,
2489 );
2490 match query_result {
2491 Err(Error::GroveDB(e))
2492 if matches!(
2493 e.as_ref(),
2494 GroveError::PathKeyNotFound(_)
2495 | GroveError::PathNotFound(_)
2496 | GroveError::PathParentLayerNotFound(_)
2497 ) =>
2498 {
2499 Ok((QueryResultElements::new(), 0))
2500 }
2501 _ => {
2502 let (data, skipped) = query_result?;
2503 {
2504 Ok((data, skipped))
2505 }
2506 }
2507 }
2508 }
2509}
2510
2511impl<'a> From<&DriveDocumentQuery<'a>> for BTreeMap<String, Value> {
2513 fn from(query: &DriveDocumentQuery<'a>) -> Self {
2514 let mut response = BTreeMap::<String, Value>::new();
2515
2516 response.insert(
2519 "contract_id".to_string(),
2520 Value::Identifier(query.contract.id().to_buffer()),
2521 );
2522
2523 response.insert(
2526 "document_type_name".to_string(),
2527 Value::Text(query.document_type.name().to_string()),
2528 );
2529
2530 let all_where_clauses: Vec<WhereClause> = query.internal_clauses.clone().into();
2532 response.insert(
2533 "where".to_string(),
2534 Value::Array(all_where_clauses.into_iter().map(|v| v.into()).collect()),
2535 );
2536
2537 if let Some(offset) = query.offset {
2539 response.insert("offset".to_string(), Value::U16(offset));
2540 };
2541 if let Some(limit) = query.limit {
2543 response.insert("limit".to_string(), Value::U16(limit));
2544 };
2545 let order_by = &query.order_by;
2547 let value: Vec<Value> = order_by
2548 .into_iter()
2549 .map(|(_k, v)| v.clone().into())
2550 .collect();
2551 response.insert("orderBy".to_string(), Value::Array(value));
2552
2553 if let Some(start_at) = query.start_at {
2555 let v = Value::Identifier(start_at);
2556 if query.start_at_included {
2557 response.insert("startAt".to_string(), v);
2558 } else {
2559 response.insert("startAfter".to_string(), v);
2560 }
2561 };
2562
2563 if let Some(block_time_ms) = query.block_time_ms {
2565 response.insert("blockTime".to_string(), Value::U64(block_time_ms));
2566 };
2567
2568 response
2569 }
2570}
2571
2572#[cfg(feature = "server")]
2573#[cfg(test)]
2574mod tests {
2575
2576 use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
2577
2578 use dpp::prelude::Identifier;
2579 use grovedb::Query;
2580 use indexmap::IndexMap;
2581 use rand::prelude::StdRng;
2582 use rand::SeedableRng;
2583 use serde_json::json;
2584 use std::borrow::Cow;
2585 use std::collections::BTreeMap;
2586 use std::option::Option::None;
2587 use tempfile::TempDir;
2588
2589 use crate::drive::Drive;
2590 use crate::query::{
2591 DriveDocumentQuery, InternalClauses, OrderClause, WhereClause, WhereOperator,
2592 };
2593 use crate::util::storage_flags::StorageFlags;
2594
2595 use dpp::data_contract::DataContract;
2596
2597 use serde_json::Value::Null;
2598
2599 use crate::config::DriveConfig;
2600 use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure;
2601 use dpp::block::block_info::BlockInfo;
2602 use dpp::data_contract::accessors::v0::DataContractV0Getters;
2603 use dpp::data_contracts::SystemDataContract;
2604 use dpp::document::DocumentV0;
2605 use dpp::platform_value::string_encoding::Encoding;
2606 use dpp::platform_value::Value;
2607 use dpp::system_data_contracts::load_system_data_contract;
2608 use dpp::tests::fixtures::{get_data_contract_fixture, get_dpns_data_contract_fixture};
2609 use dpp::tests::json_document::json_document_to_contract;
2610 use dpp::util::cbor_serializer;
2611 use dpp::version::PlatformVersion;
2612
2613 fn setup_family_contract() -> (Drive, DataContract) {
2614 let tmp_dir = TempDir::new().unwrap();
2615
2616 let platform_version = PlatformVersion::latest();
2617
2618 let (drive, _) = Drive::open(tmp_dir, None).expect("expected to open Drive successfully");
2619
2620 drive
2621 .create_initial_state_structure(None, platform_version)
2622 .expect("expected to create root tree successfully");
2623
2624 let contract_path = "tests/supporting_files/contract/family/family-contract.json";
2625
2626 let contract = json_document_to_contract(contract_path, false, platform_version)
2628 .expect("expected to get document");
2629
2630 let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0)));
2631 drive
2632 .apply_contract(
2633 &contract,
2634 BlockInfo::default(),
2635 true,
2636 storage_flags,
2637 None,
2638 platform_version,
2639 )
2640 .expect("expected to apply contract successfully");
2641
2642 (drive, contract)
2643 }
2644
2645 fn setup_withdrawal_contract() -> (Drive, DataContract) {
2646 let tmp_dir = TempDir::new().unwrap();
2647
2648 let platform_version = PlatformVersion::latest();
2649
2650 let (drive, _) = Drive::open(tmp_dir, None).expect("expected to open Drive successfully");
2651
2652 drive
2653 .create_initial_state_structure(None, platform_version)
2654 .expect("expected to create root tree successfully");
2655
2656 let contract = load_system_data_contract(SystemDataContract::Withdrawals, platform_version)
2658 .expect("load system contact");
2659
2660 let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0)));
2661 drive
2662 .apply_contract(
2663 &contract,
2664 BlockInfo::default(),
2665 true,
2666 storage_flags,
2667 None,
2668 platform_version,
2669 )
2670 .expect("expected to apply contract successfully");
2671
2672 (drive, contract)
2673 }
2674
2675 fn setup_family_birthday_contract() -> (Drive, DataContract) {
2676 let drive = setup_drive_with_initial_state_structure(None);
2677
2678 let platform_version = PlatformVersion::latest();
2679
2680 let contract_path =
2681 "tests/supporting_files/contract/family/family-contract-with-birthday.json";
2682
2683 let contract = json_document_to_contract(contract_path, false, platform_version)
2685 .expect("expected to get document");
2686 let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0)));
2687 drive
2688 .apply_contract(
2689 &contract,
2690 BlockInfo::default(),
2691 true,
2692 storage_flags,
2693 None,
2694 platform_version,
2695 )
2696 .expect("expected to apply contract successfully");
2697
2698 (drive, contract)
2699 }
2700
2701 #[test]
2702 fn test_drive_query_from_to_cbor() {
2703 let config = DriveConfig::default();
2704 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2705 let document_type = contract
2706 .document_type_for_name("niceDocument")
2707 .expect("expected to get nice document");
2708 let start_after = Identifier::random();
2709
2710 let query_value = json!({
2711 "contract_id": contract.id(),
2712 "document_type_name": document_type.name(),
2713 "where": [
2714 ["firstName", "<", "Gilligan"],
2715 ["lastName", "=", "Doe"]
2716 ],
2717 "limit": 100u16,
2718 "offset": 10u16,
2719 "orderBy": [
2720 ["firstName", "asc"],
2721 ["lastName", "desc"],
2722 ],
2723 "startAfter": start_after,
2724 "blockTime": 13453432u64,
2725 });
2726
2727 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2728 .expect("expected to serialize to cbor");
2729 let query =
2730 DriveDocumentQuery::from_cbor(where_cbor.as_slice(), &contract, document_type, &config)
2731 .expect("deserialize cbor shouldn't fail");
2732
2733 let cbor = query.to_cbor().expect("should serialize cbor");
2734
2735 let deserialized = DriveDocumentQuery::from_cbor(&cbor, &contract, document_type, &config)
2736 .expect("should deserialize cbor");
2737
2738 assert_eq!(query, deserialized);
2739
2740 assert_eq!(deserialized.start_at, Some(start_after.to_buffer()));
2741 assert!(!deserialized.start_at_included);
2742 assert_eq!(deserialized.block_time_ms, Some(13453432u64));
2743 }
2744
2745 #[test]
2746 fn test_invalid_query_ranges_different_fields() {
2747 let query_value = json!({
2748 "where": [
2749 ["firstName", "<", "Gilligan"],
2750 ["lastName", "<", "Michelle"],
2751 ],
2752 "limit": 100,
2753 "orderBy": [
2754 ["firstName", "asc"],
2755 ["lastName", "asc"],
2756 ]
2757 });
2758 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2759 let document_type = contract
2760 .document_type_for_name("niceDocument")
2761 .expect("expected to get nice document");
2762
2763 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2764 .expect("expected to serialize to cbor");
2765 DriveDocumentQuery::from_cbor(
2766 where_cbor.as_slice(),
2767 &contract,
2768 document_type,
2769 &DriveConfig::default(),
2770 )
2771 .expect_err("all ranges must be on same field");
2772 }
2773
2774 #[test]
2775 fn test_invalid_query_extra_invalid_field() {
2776 let query_value = json!({
2777 "where": [
2778 ["firstName", "<", "Gilligan"],
2779 ],
2780 "limit": 100,
2781 "orderBy": [
2782 ["firstName", "asc"],
2783 ["lastName", "asc"],
2784 ],
2785 "invalid": 0,
2786 });
2787 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2788 let document_type = contract
2789 .document_type_for_name("niceDocument")
2790 .expect("expected to get nice document");
2791
2792 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2793 .expect("expected to serialize to cbor");
2794 DriveDocumentQuery::from_cbor(
2795 where_cbor.as_slice(),
2796 &contract,
2797 document_type,
2798 &DriveConfig::default(),
2799 )
2800 .expect_err("fields of queries must of defined supported types (where, limit, orderBy...)");
2801 }
2802
2803 #[test]
2804 fn test_invalid_query_conflicting_clauses() {
2805 let query_value = json!({
2806 "where": [
2807 ["firstName", "<", "Gilligan"],
2808 ["firstName", ">", "Gilligan"],
2809 ],
2810 "limit": 100,
2811 "orderBy": [
2812 ["firstName", "asc"],
2813 ["lastName", "asc"],
2814 ],
2815 });
2816
2817 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2818 let document_type = contract
2819 .document_type_for_name("niceDocument")
2820 .expect("expected to get nice document");
2821
2822 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2823 .expect("expected to serialize to cbor");
2824 DriveDocumentQuery::from_cbor(
2825 where_cbor.as_slice(),
2826 &contract,
2827 document_type,
2828 &DriveConfig::default(),
2829 )
2830 .expect_err("the query should not be created");
2831 }
2832
2833 #[test]
2834 fn test_valid_query_groupable_meeting_clauses() {
2835 let query_value = json!({
2836 "where": [
2837 ["firstName", "<=", "Gilligan"],
2838 ["firstName", ">", "Gilligan"],
2839 ],
2840 "limit": 100,
2841 "orderBy": [
2842 ["firstName", "asc"],
2843 ["lastName", "asc"],
2844 ],
2845 });
2846
2847 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2848 let document_type = contract
2849 .document_type_for_name("niceDocument")
2850 .expect("expected to get nice document");
2851
2852 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2853 .expect("expected to serialize to cbor");
2854 DriveDocumentQuery::from_cbor(
2855 where_cbor.as_slice(),
2856 &contract,
2857 document_type,
2858 &DriveConfig::default(),
2859 )
2860 .expect("the query should be created");
2861 }
2862
2863 #[test]
2864 fn test_valid_query_query_field_at_max_length() {
2865 let long_string = "t".repeat(255);
2866 let query_value = json!({
2867 "where": [
2868 ["firstName", "<", long_string],
2869 ],
2870 "limit": 100,
2871 "orderBy": [
2872 ["firstName", "asc"],
2873 ["lastName", "asc"],
2874 ],
2875 });
2876 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
2877 let document_type = contract
2878 .document_type_for_name("niceDocument")
2879 .expect("expected to get nice document");
2880
2881 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2882 .expect("expected to serialize to cbor");
2883 DriveDocumentQuery::from_cbor(
2884 where_cbor.as_slice(),
2885 &contract,
2886 document_type,
2887 &DriveConfig::default(),
2888 )
2889 .expect("query should be fine for a 255 byte long string");
2890 }
2891
2892 #[test]
2893 fn test_valid_query_drive_document_query() {
2894 let platform_version = PlatformVersion::latest();
2895 let mut rng = StdRng::seed_from_u64(5);
2896 let contract =
2897 get_dpns_data_contract_fixture(Some(Identifier::random_with_rng(&mut rng)), 0, 1)
2898 .data_contract_owned();
2899 let domain = contract
2900 .document_type_for_name("domain")
2901 .expect("expected to get domain");
2902
2903 let query_asc = DriveDocumentQuery {
2904 contract: &contract,
2905 document_type: domain,
2906 internal_clauses: InternalClauses {
2907 primary_key_in_clause: None,
2908 primary_key_equal_clause: None,
2909 in_clause: None,
2910 range_clause: Some(WhereClause {
2911 field: "records.identity".to_string(),
2912 operator: WhereOperator::LessThan,
2913 value: Value::Identifier(
2914 Identifier::from_string(
2915 "AYN4srupPWDrp833iG5qtmaAsbapNvaV7svAdncLN5Rh",
2916 Encoding::Base58,
2917 )
2918 .unwrap()
2919 .to_buffer(),
2920 ),
2921 }),
2922 equal_clauses: BTreeMap::new(),
2923 },
2924 offset: None,
2925 limit: Some(6),
2926 order_by: vec![(
2927 "records.identity".to_string(),
2928 OrderClause {
2929 field: "records.identity".to_string(),
2930 ascending: false,
2931 },
2932 )]
2933 .into_iter()
2934 .collect(),
2935 start_at: None,
2936 start_at_included: false,
2937 block_time_ms: None,
2938 };
2939
2940 let path_query = query_asc
2941 .construct_path_query(None, platform_version)
2942 .expect("expected to create path query");
2943
2944 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 } }");
2945
2946 let encoded = bincode::encode_to_vec(&path_query, bincode::config::standard())
2948 .expect("Failed to serialize PathQuery");
2949
2950 let hex_string = hex::encode(encoded);
2952
2953 assert_eq!(hex_string, "050140201da29f488023e306ff9a680bc9837153fb0778c8ee9c934a87dc0de1d69abd3c010106646f6d61696e107265636f7264732e6964656e74697479010105208dc201fd7ad7905f8a84d66218e2b387daea7fe4739ae0e21e8c3ee755e6a2c00101010001010103000000000001010000010101000101010300000000000000010600");
2957 }
2958
2959 #[test]
2960 fn test_invalid_query_field_too_long() {
2961 let (drive, contract) = setup_family_contract();
2962
2963 let platform_version = PlatformVersion::latest();
2964
2965 let document_type = contract
2966 .document_type_for_name("person")
2967 .expect("expected to get a document type");
2968
2969 let too_long_string = "t".repeat(256);
2970 let query_value = json!({
2971 "where": [
2972 ["firstName", "<", too_long_string],
2973 ],
2974 "limit": 100,
2975 "orderBy": [
2976 ["firstName", "asc"],
2977 ["lastName", "asc"],
2978 ],
2979 });
2980
2981 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
2982 .expect("expected to serialize to cbor");
2983 let query = DriveDocumentQuery::from_cbor(
2984 where_cbor.as_slice(),
2985 &contract,
2986 document_type,
2987 &DriveConfig::default(),
2988 )
2989 .expect("fields of queries length must be under 256 bytes long");
2990 query
2991 .execute_raw_results_no_proof(&drive, None, None, platform_version)
2992 .expect_err("fields of queries length must be under 256 bytes long");
2993 }
2994
2995 #[test]
3051 fn test_valid_query_timestamp_field_with_null_value() {
3052 let (drive, contract) = setup_family_birthday_contract();
3053
3054 let platform_version = PlatformVersion::latest();
3055
3056 let document_type = contract
3057 .document_type_for_name("person")
3058 .expect("expected to get a document type");
3059
3060 let query_value = json!({
3061 "where": [
3062 ["birthday", ">=", Null],
3063 ],
3064 "limit": 100,
3065 "orderBy": [
3066 ["birthday", "asc"],
3067 ],
3068 });
3069
3070 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3071 .expect("expected to serialize to cbor");
3072 let query = DriveDocumentQuery::from_cbor(
3073 where_cbor.as_slice(),
3074 &contract,
3075 document_type,
3076 &DriveConfig::default(),
3077 )
3078 .expect("The query itself should be valid for a null type");
3079 query
3080 .execute_raw_results_no_proof(&drive, None, None, platform_version)
3081 .expect("a Null value doesn't make sense for a float");
3082 }
3083
3084 #[test]
3085 fn test_invalid_query_in_with_empty_array() {
3086 let (drive, contract) = setup_family_contract();
3087
3088 let platform_version = PlatformVersion::latest();
3089
3090 let document_type = contract
3091 .document_type_for_name("person")
3092 .expect("expected to get a document type");
3093
3094 let query_value = json!({
3095 "where": [
3096 ["firstName", "in", []],
3097 ],
3098 "limit": 100,
3099 "orderBy": [
3100 ["firstName", "asc"],
3101 ],
3102 });
3103
3104 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3105 .expect("expected to serialize to cbor");
3106 let query = DriveDocumentQuery::from_cbor(
3107 where_cbor.as_slice(),
3108 &contract,
3109 document_type,
3110 &DriveConfig::default(),
3111 )
3112 .expect("query should be valid for empty array");
3113
3114 query
3115 .execute_raw_results_no_proof(&drive, None, None, platform_version)
3116 .expect_err("query should not be able to execute for empty array");
3117 }
3118
3119 #[test]
3120 fn test_invalid_query_in_too_many_elements() {
3121 let (drive, contract) = setup_family_contract();
3122
3123 let platform_version = PlatformVersion::latest();
3124
3125 let document_type = contract
3126 .document_type_for_name("person")
3127 .expect("expected to get a document type");
3128
3129 let mut array: Vec<String> = Vec::with_capacity(101);
3130 for _ in 0..array.capacity() {
3131 array.push(String::from("a"));
3132 }
3133 let query_value = json!({
3134 "where": [
3135 ["firstName", "in", array],
3136 ],
3137 "limit": 100,
3138 "orderBy": [
3139 ["firstName", "asc"],
3140 ],
3141 });
3142
3143 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3144 .expect("expected to serialize to cbor");
3145 let query = DriveDocumentQuery::from_cbor(
3146 where_cbor.as_slice(),
3147 &contract,
3148 document_type,
3149 &DriveConfig::default(),
3150 )
3151 .expect("query is valid for too many elements");
3152
3153 query
3154 .execute_raw_results_no_proof(&drive, None, None, platform_version)
3155 .expect_err("query should not be able to execute with too many elements");
3156 }
3157
3158 #[test]
3159 fn test_invalid_query_in_unique_elements() {
3160 let (drive, contract) = setup_family_contract();
3161
3162 let platform_version = PlatformVersion::latest();
3163
3164 let document_type = contract
3165 .document_type_for_name("person")
3166 .expect("expected to get a document type");
3167
3168 let query_value = json!({
3169 "where": [
3170 ["firstName", "in", ["a", "a"]],
3171 ],
3172 "limit": 100,
3173 "orderBy": [
3174 ["firstName", "asc"],
3175 ],
3176 });
3177
3178 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3179 .expect("expected to serialize to cbor");
3180
3181 let query = DriveDocumentQuery::from_cbor(
3185 where_cbor.as_slice(),
3186 &contract,
3187 document_type,
3188 &DriveConfig::default(),
3189 )
3190 .expect("the query should be created");
3191
3192 query
3193 .execute_raw_results_no_proof(&drive, None, None, platform_version)
3194 .expect_err("there should be no duplicates values for In query");
3195 }
3196
3197 #[test]
3198 fn test_invalid_query_starts_with_empty_string() {
3199 let query_value = json!({
3200 "where": [
3201 ["firstName", "startsWith", ""],
3202 ],
3203 "limit": 100,
3204 "orderBy": [
3205 ["firstName", "asc"],
3206 ],
3207 });
3208
3209 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
3210 let document_type = contract
3211 .document_type_for_name("niceDocument")
3212 .expect("expected to get nice document");
3213
3214 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3215 .expect("expected to serialize to cbor");
3216 DriveDocumentQuery::from_cbor(
3217 where_cbor.as_slice(),
3218 &contract,
3219 document_type,
3220 &DriveConfig::default(),
3221 )
3222 .expect_err("starts with can not start with an empty string");
3223 }
3224
3225 #[test]
3226 fn test_invalid_query_limit_too_high() {
3227 let query_value = json!({
3228 "where": [
3229 ["firstName", "startsWith", "a"],
3230 ],
3231 "limit": 101,
3232 "orderBy": [
3233 ["firstName", "asc"],
3234 ],
3235 });
3236
3237 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
3238 let document_type = contract
3239 .document_type_for_name("niceDocument")
3240 .expect("expected to get nice document");
3241
3242 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3243 .expect("expected to serialize to cbor");
3244 DriveDocumentQuery::from_cbor(
3245 where_cbor.as_slice(),
3246 &contract,
3247 document_type,
3248 &DriveConfig::default(),
3249 )
3250 .expect_err("starts with can not start with an empty string");
3251 }
3252
3253 #[test]
3254 fn test_invalid_query_limit_too_low() {
3255 let query_value = json!({
3256 "where": [
3257 ["firstName", "startsWith", "a"],
3258 ],
3259 "limit": -1,
3260 "orderBy": [
3261 ["firstName", "asc"],
3262 ],
3263 });
3264
3265 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
3266 let document_type = contract
3267 .document_type_for_name("niceDocument")
3268 .expect("expected to get nice document");
3269
3270 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3271 .expect("expected to serialize to cbor");
3272 DriveDocumentQuery::from_cbor(
3273 where_cbor.as_slice(),
3274 &contract,
3275 document_type,
3276 &DriveConfig::default(),
3277 )
3278 .expect_err("starts with can not start with an empty string");
3279 }
3280
3281 #[test]
3282 fn test_invalid_query_limit_zero() {
3283 let query_value = json!({
3284 "where": [
3285 ["firstName", "startsWith", "a"],
3286 ],
3287 "limit": 0,
3288 "orderBy": [
3289 ["firstName", "asc"],
3290 ],
3291 });
3292
3293 let contract = get_data_contract_fixture(None, 0, 1).data_contract_owned();
3294 let document_type = contract
3295 .document_type_for_name("niceDocument")
3296 .expect("expected to get nice document");
3297
3298 let where_cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None)
3299 .expect("expected to serialize to cbor");
3300 DriveDocumentQuery::from_cbor(
3301 where_cbor.as_slice(),
3302 &contract,
3303 document_type,
3304 &DriveConfig::default(),
3305 )
3306 .expect_err("starts with can not start with an empty string");
3307 }
3308
3309 #[test]
3310 fn test_withdrawal_query_with_missing_transaction_index() {
3311 let (_, contract) = setup_withdrawal_contract();
3313 let platform_version = PlatformVersion::latest();
3314
3315 let document_type_name = "withdrawal";
3316 let document_type = contract
3317 .document_type_for_name(document_type_name)
3318 .expect("expected to get document type");
3319
3320 let drive_document_query = DriveDocumentQuery {
3322 contract: &contract,
3323 document_type,
3324 internal_clauses: InternalClauses {
3325 primary_key_in_clause: None,
3326 primary_key_equal_clause: None,
3327 in_clause: Some(WhereClause {
3328 field: "status".to_string(),
3329 operator: WhereOperator::In,
3330 value: Value::Array(vec![
3331 Value::U64(0),
3332 Value::U64(1),
3333 Value::U64(2),
3334 Value::U64(3),
3335 Value::U64(4),
3336 ]),
3337 }),
3338 range_clause: None,
3339 equal_clauses: BTreeMap::default(),
3340 },
3341 offset: None,
3342 limit: Some(3),
3343 order_by: IndexMap::from([
3344 (
3345 "status".to_string(),
3346 OrderClause {
3347 field: "status".to_string(),
3348 ascending: true,
3349 },
3350 ),
3351 (
3352 "transactionIndex".to_string(),
3353 OrderClause {
3354 field: "transactionIndex".to_string(),
3355 ascending: true,
3356 },
3357 ),
3358 ]),
3359 start_at: Some([3u8; 32]),
3360 start_at_included: false,
3361 block_time_ms: None,
3362 };
3363
3364 let mut properties = BTreeMap::new();
3366 properties.insert("status".to_string(), Value::U64(0));
3367 let starts_at_document = DocumentV0 {
3370 id: Identifier::from([3u8; 32]), owner_id: Identifier::random(),
3372 properties,
3373 revision: None,
3374 created_at: None,
3375 updated_at: None,
3376 transferred_at: None,
3377 created_at_block_height: None,
3378 updated_at_block_height: None,
3379 transferred_at_block_height: None,
3380 created_at_core_block_height: None,
3381 updated_at_core_block_height: None,
3382 transferred_at_core_block_height: None,
3383 creator_id: None,
3384 }
3385 .into();
3386
3387 let result = drive_document_query
3389 .construct_path_query(Some(starts_at_document), platform_version)
3390 .expect("expected to construct a path query");
3391
3392 assert_eq!(
3393 result
3394 .clone()
3395 .query
3396 .query
3397 .default_subquery_branch
3398 .subquery
3399 .expect("expected subquery")
3400 .items,
3401 Query::new_range_full().items
3402 );
3403 }
3404}