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