drive/query/
mod.rs

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// Imports available when either "server" or "verify" features are enabled
14#[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};
60// Crate-local unconditional imports
61use crate::config::DriveConfig;
62// Crate-local unconditional imports
63use crate::util::common::encode::encode_u64;
64#[cfg(feature = "server")]
65use crate::util::grove_operations::QueryType::StatefulQuery;
66
67// Module declarations that are conditional on either "server" or "verify" features
68#[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// Module declarations exclusively for "server" feature
78#[cfg(feature = "server")]
79mod test_index;
80
81#[cfg(any(feature = "server", feature = "verify"))]
82/// Vote poll vote state query module
83pub mod vote_poll_vote_state_query;
84#[cfg(any(feature = "server", feature = "verify"))]
85/// Vote Query module
86pub mod vote_query;
87
88#[cfg(any(feature = "server", feature = "verify"))]
89/// Vote poll contestant votes query module
90pub mod vote_poll_contestant_votes_query;
91
92#[cfg(any(feature = "server", feature = "verify"))]
93/// Vote polls by end date query
94pub mod vote_polls_by_end_date_query;
95
96#[cfg(any(feature = "server", feature = "verify"))]
97/// Vote polls by document type query
98pub mod vote_polls_by_document_type_query;
99
100/// Function type for looking up a contract by identifier
101///
102/// This function is used to look up a contract by its identifier.
103/// It should be implemented by the caller in order to provide data
104/// contract required for operations like proof verification.
105#[cfg(any(feature = "server", feature = "verify"))]
106pub type ContractLookupFn<'a> =
107    dyn Fn(&Identifier) -> Result<Option<Arc<DataContract>>, Error> + 'a;
108
109/// Creates a [ContractLookupFn] function that returns provided data contract when requested.
110///
111/// # Arguments
112///
113/// * `data_contract` - [Arc<DataContract>](DataContract) to return
114///
115/// # Returns
116///
117/// [ContractLookupFn] that will return the `data_contract`, or `None` if
118/// the requested contract is not the same as the provided one.
119#[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/// A query to get the votes given out by an identity
133#[cfg(any(feature = "server", feature = "verify"))]
134pub mod contested_resource_votes_given_by_identity_query;
135/// A query to get contested documents before they have been awarded
136#[cfg(any(feature = "server", feature = "verify"))]
137pub mod drive_contested_document_query;
138
139/// A query to get the block counts of proposers in an epoch
140#[cfg(any(feature = "server", feature = "verify"))]
141pub mod proposer_block_count_query;
142
143/// A query to get the identity's token balance
144#[cfg(any(feature = "server", feature = "verify"))]
145pub mod identity_token_balance_drive_query;
146/// A query to get the identity's token info
147#[cfg(any(feature = "server", feature = "verify"))]
148pub mod identity_token_info_drive_query;
149
150/// Document subscription filtering
151#[cfg(any(feature = "server", feature = "verify"))]
152pub mod filter;
153/// A query to get the token's status
154#[cfg(any(feature = "server", feature = "verify"))]
155pub mod token_status_drive_query;
156
157/// A Query Syntax Validation Result that contains data
158pub type QuerySyntaxValidationResult<TData> = ValidationResult<TData, QuerySyntaxError>;
159
160/// A Query Syntax Validation Result
161pub type QuerySyntaxSimpleValidationResult = SimpleValidationResult<QuerySyntaxError>;
162
163#[cfg(any(feature = "server", feature = "verify"))]
164/// Represents a starting point for a query based on a specific document.
165///
166/// This struct encapsulates all the necessary details to define the starting
167/// conditions for a query, including the document to start from, its type,
168/// associated index property, and whether the document itself should be included
169/// in the query results.
170#[derive(Debug, Clone)]
171pub struct StartAtDocument<'a> {
172    /// The document that serves as the starting point for the query.
173    pub document: Document,
174
175    /// The type of the document, providing metadata about its schema and structure.
176    pub document_type: DocumentTypeRef<'a>,
177
178    /// Indicates whether the starting document itself should be included in the query results.
179    /// - `true`: The document is included in the results.
180    /// - `false`: The document is excluded, and the query starts from the next matching document.
181    pub included: bool,
182}
183
184/// Internal clauses struct
185#[cfg(any(feature = "server", feature = "verify"))]
186#[derive(Clone, Debug, PartialEq, Default)]
187pub struct InternalClauses {
188    /// Primary key in clause
189    pub primary_key_in_clause: Option<WhereClause>,
190    /// Primary key equal clause
191    pub primary_key_equal_clause: Option<WhereClause>,
192    /// In clause
193    pub in_clause: Option<WhereClause>,
194    /// Range clause
195    pub range_clause: Option<WhereClause>,
196    /// Equal clause
197    pub equal_clauses: BTreeMap<String, WhereClause>,
198}
199
200impl InternalClauses {
201    #[cfg(any(feature = "server", feature = "verify"))]
202    /// Returns true if the clause is a valid format.
203    pub fn verify(&self) -> bool {
204        // There can only be 1 primary key clause, or many other clauses
205        if self
206            .primary_key_in_clause
207            .is_some()
208            .bitxor(self.primary_key_equal_clause.is_some())
209        {
210            // One is set, all rest must be empty
211            !(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    /// Returns true if the query clause is for primary keys.
221    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    /// Returns true if self is empty.
227    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    /// Extracts the `WhereClause`s and returns them as type `InternalClauses`.
237    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    /// Validate this collection of InternalClauses against the document schema
310    #[cfg(any(feature = "server", feature = "verify"))]
311    pub fn validate_against_schema(
312        &self,
313        document_type: DocumentTypeRef,
314    ) -> QuerySyntaxSimpleValidationResult {
315        // Basic composition
316        if !self.verify() {
317            return QuerySyntaxSimpleValidationResult::new_with_error(
318                QuerySyntaxError::InvalidWhereClauseComponents(
319                    "invalid composition of where clauses",
320                ),
321            );
322        }
323
324        // Validate in_clause against schema
325        if let Some(in_clause) = &self.in_clause {
326            // Forbid $id in non-primary-key clauses
327            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        // Validate range_clause against schema
341        if let Some(range_clause) = &self.range_clause {
342            // Forbid $id in non-primary-key clauses
343            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        // Validate equal_clauses against schema
357        for (field, eq_clause) in &self.equal_clauses {
358            // Forbid $id in non-primary-key clauses
359            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        // Validate primary key clauses typing
373        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            // enforce array shape and no duplicates/size
393            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/// Drive query struct
441#[derive(Debug, PartialEq, Clone)]
442pub struct DriveDocumentQuery<'a> {
443    ///DataContract
444    pub contract: &'a DataContract,
445    /// Document type
446    pub document_type: DocumentTypeRef<'a>,
447    /// Internal clauses
448    pub internal_clauses: InternalClauses,
449    /// Offset
450    pub offset: Option<u16>,
451    /// Limit
452    pub limit: Option<u16>,
453    /// Order by
454    pub order_by: IndexMap<String, OrderClause>,
455    /// Start at document id
456    pub start_at: Option<[u8; 32]>,
457    /// Start at included
458    pub start_at_included: bool,
459    /// Block time
460    pub block_time_ms: Option<u64>,
461}
462
463impl<'a> DriveDocumentQuery<'a> {
464    /// Gets a document by their primary key
465    #[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    /// Returns any item
496    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    /// Returns all items
512    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    /// Returns true if the query clause if for primary keys.
532    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    /// Converts a query CBOR to a `DriveQuery`.
549    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    /// Converts a query Value to a `DriveQuery`.
565    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    /// Converts a query Value to a `DriveQuery`.
577    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    /// Converts a query Value to a `DriveQuery`.
742    #[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    /// Converts a SQL expression to a `DriveQuery`.
824    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        // Should ideally iterate over each statement
834        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        // Grab the select section of the query
895        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        // Get the document type from the 'from' section
904        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        // Restrictions
928        // only binary where clauses are supported
929        // i.e. [<fieldname>, <operator>, <value>]
930        // [and] is used to separate where clauses
931        // currently where clauses are either binary operations or list descriptions (in clauses)
932        // hence once [and] is encountered [left] and [right] must be only one of the above
933        // i.e other where clauses
934        // e.g. firstname = wisdom and lastname = ogwu
935        // if op is not [and] then [left] or [right] must not be a binary operation or list description
936        let mut all_where_clauses: Vec<WhereClause> = Vec::new();
937        let selection_tree = select.selection.as_ref();
938
939        // Where clauses are optional
940        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; //todo
951        let start_after_option = None; //todo
952        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    /// Serialize drive query to CBOR format.
985    ///
986    /// FIXME: The data contract is only referred as ID, and document type as its name.
987    /// This can change in the future to include full data contract and document type.
988    #[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    /// Operations to construct a path query.
1001    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    /// Operations to construct a path query.
1030    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        // First we should get the overall document_type_path
1040        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                // First if we have a startAt or startsAfter we must get the element
1051                // from the backing store
1052
1053                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    /// Operations to construct a path query.
1137    pub fn construct_path_query(
1138        &self,
1139        starts_at_document: Option<Document>,
1140        platform_version: &PlatformVersion,
1141    ) -> Result<PathQuery, Error> {
1142        // First we should get the overall document_type_path
1143        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    /// Returns a path query given a document type path and starting document.
1168    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        // Add primary key ($id) subtree
1177        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 the documents keep history then we should insert a subquery
1190                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            // This is for a range
1203            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            // If there is a start_at_document, we need to get the value that it has for the
1219            // current field.
1220            let starts_at_key_option = match starts_at_document {
1221                None => None,
1222                Some((document, included)) => {
1223                    // if the key doesn't exist then we should ignore the starts at key
1224                    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 the documents keep history then we should insert a subquery
1269                    if let Some(_block_time) = self.block_time_ms {
1270                        //todo
1271                        return Err(Error::Query(QuerySyntaxError::Unsupported(
1272                            "Not yet implemented".to_string(),
1273                        )));
1274                        // in order to be able to do this we would need limited subqueries
1275                        // as we only want the first element before the block_time
1276
1277                        // let encoded_block_time = encode_float(block_time)?;
1278                        // let mut sub_query = Query::new_with_direction(false);
1279                        // sub_query.insert_range_to_inclusive(..=encoded_block_time);
1280                        // query.set_subquery(sub_query);
1281                    } 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                // this is a range on all elements
1292                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 the documents keep history then we should insert a subquery
1310                    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                        // in order to be able to do this we would need limited subqueries
1315                        // as we only want the first element before the block_time
1316
1317                        // let encoded_block_time = encode_float(block_time)?;
1318                        // let mut sub_query = Query::new_with_direction(false);
1319                        // sub_query.insert_range_to_inclusive(..=encoded_block_time);
1320                        // query.set_subquery(sub_query);
1321                    } 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    /// Finds the best index for the query.
1336    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            //if there is an in_field, it always takes precedence
1360        }
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    /// Returns a `QueryItem` given a start key and query direction.
1398    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    /// Returns a `Query` that either starts at or after the given document ID if given.
1408    fn inner_query_from_starts_at_for_id(
1409        starts_at_document: Option<&StartAtDocument>,
1410        left_to_right: bool,
1411    ) -> Query {
1412        // We only need items after the start at document
1413        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            // No starts at document, take all NULL items
1427            inner_query.insert_all();
1428        }
1429        inner_query
1430    }
1431
1432    #[cfg(any(feature = "server", feature = "verify"))]
1433    /// Returns a `Query` that either starts at or after the given key.
1434    fn inner_query_starts_from_key(
1435        start_at_key: Option<Vec<u8>>,
1436        left_to_right: bool,
1437        included: bool,
1438    ) -> Query {
1439        // We only need items after the start at document
1440        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            //todo: really not sure if this is correct
1462            // Should investigate more
1463            inner_query.insert_key(vec![]);
1464        }
1465
1466        inner_query
1467    }
1468
1469    #[cfg(any(feature = "server", feature = "verify"))]
1470    /// Returns a `Query` that either starts at or after the given document if given.
1471    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            // We only need items after the start at document
1485            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            // We want to get items starting at the start key
1492            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            // No starts at document, take all NULL items
1511            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>, //for key level, included
1521        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    /// Recursively queries as long as there are leftover index properties.
1559    /// The in_start_at_document_sub_path_needing_conditional is interesting.
1560    /// It indicates whether the start at document should be applied as a conditional
1561    /// For example if we have a tree
1562    /// Root
1563    /// ├── model
1564    /// │   ├── sedan
1565    /// │   │   ├── brand_name
1566    /// │   │   │   ├── Honda
1567    /// │   │   │   │   ├── car_type
1568    /// │   │   │   │   │   ├── Accord
1569    /// │   │   │   │   │   │   ├── 0
1570    /// │   │   │   │   │   │   │   ├── a47d2...
1571    /// │   │   │   │   │   │   │   ├── e19c8...
1572    /// │   │   │   │   │   │   │   └── f1a7b...
1573    /// │   │   │   │   │   └── Civic
1574    /// │   │   │   │   │       ├── 0
1575    /// │   │   │   │   │       │   ├── b65a7...
1576    /// │   │   │   │   │       │   └── c43de...
1577    /// │   │   │   ├── Toyota
1578    /// │   │   │   │   ├── car_type
1579    /// │   │   │   │   │   ├── Camry
1580    /// │   │   │   │   │   │   ├── 0
1581    /// │   │   │   │   │   │   │   └── 1a9d2...
1582    /// │   │   │   │   │   └── Corolla
1583    /// │   │   │   │   │       ├── 0
1584    /// │   │   │   │   │       │   ├── 3f7b4...
1585    /// │   │   │   │   │       │   ├── 4e8fa...
1586    /// │   │   │   │   │       │   └── 9b1c6...
1587    /// │   ├── suv
1588    /// │   │   ├── brand_name
1589    /// │   │   │   ├── Ford*
1590    /// │   │   │   │   ├── car_type*
1591    /// │   │   │   │   │   ├── Escape*
1592    /// │   │   │   │   │   │   ├── 0
1593    /// │   │   │   │   │   │   │   ├── 102bc...
1594    /// │   │   │   │   │   │   │   ├── 29f8e... <- Set After this document
1595    /// │   │   │   │   │   │   │   └── 6b1a3...
1596    /// │   │   │   │   │   └── Explorer
1597    /// │   │   │   │   │       ├── 0
1598    /// │   │   │   │   │       │   ├── b2a9d...
1599    /// │   │   │   │   │       │   └── f4d5c...
1600    /// │   │   │   ├── Nissan
1601    /// │   │   │   │   ├── car_type
1602    /// │   │   │   │   │   ├── Rogue
1603    /// │   │   │   │   │   │   ├── 0
1604    /// │   │   │   │   │   │   │   ├── 5a9c3...
1605    /// │   │   │   │   │   │   │   └── 7e4b9...
1606    /// │   │   │   │   │   └── Murano
1607    /// │   │   │   │   │       ├── 0
1608    /// │   │   │   │   │       │   ├── 8f6a2...
1609    /// │   │   │   │   │       │   └── 9c7d4...
1610    /// │   ├── truck
1611    /// │   │   ├── brand_name
1612    /// │   │   │   ├── Ford
1613    /// │   │   │   │   ├── car_type
1614    /// │   │   │   │   │   ├── F-150
1615    /// │   │   │   │   │   │   ├── 0
1616    /// │   │   │   │   │   │   │   ├── 72a3b...
1617    /// │   │   │   │   │   │   │   └── 94c8e...
1618    /// │   │   │   │   │   └── Ranger
1619    /// │   │   │   │   │       ├── 0
1620    /// │   │   │   │   │       │   ├── 3f4b1...
1621    /// │   │   │   │   │       │   ├── 6e7d2...
1622    /// │   │   │   │   │       │   └── 8a1f5...
1623    /// │   │   │   ├── Toyota
1624    /// │   │   │   │   ├── car_type
1625    /// │   │   │   │   │   ├── Tundra
1626    /// │   │   │   │   │   │   ├── 0
1627    /// │   │   │   │   │   │   │   ├── 7c9a4...
1628    /// │   │   │   │   │   │   │   └── a5d1e...
1629    /// │   │   │   │   │   └── Tacoma
1630    /// │   │   │   │   │       ├── 0
1631    /// │   │   │   │   │       │   ├── 1e7f4...
1632    /// │   │   │   │   │       │   └── 6b9d3...
1633    ///
1634    /// let's say we are asking for suv's after 29f8e
1635    /// here the * denotes the area needing a conditional
1636    /// We need a conditional subquery on Ford to say only things after Ford (with Ford included)
1637    /// We need a conditional subquery on Escape to say only things after Escape (with Escape included)
1638    fn recursive_insert_on_query(
1639        query: &mut Query,
1640        left_over_index_properties: &[&IndexProperty],
1641        unique: bool,
1642        starts_at_document: Option<&StartAtDocument>, //for key level, included
1643        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                        // In the case things are NULL we allow to have multiple values
1654                        let inner_query = Self::inner_query_from_starts_at_for_id(
1655                            starts_at_document,
1656                            true, //for ids we always go left to right
1657                        );
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                        // we just get all by document id order ascending
1667                        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                    // We should always include if we have left_over
1712                    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                    // We place None here on purpose, this has been well-thought-out
1722                    // and should not change. The reason is that the path of the start
1723                    // at document is used only on the conditional subquery and not on the
1724                    // main query
1725                    // for example in the following
1726                    // Our query will be with $ownerId == a3f9b81c4d7e6a9f5b1c3e8a2d9c4f7b
1727                    // With start after 8f2d5
1728                    // We want to get from 2024-11-17T12:45:00Z
1729                    // withdrawal
1730                    // ├── $ownerId
1731                    // │   ├── a3f9b81c4d7e6a9f5b1c3e8a2d9c4f7b
1732                    // │   │   ├── $updatedAt
1733                    // │   │   │   ├── 2024-11-17T12:45:00Z <- conditional subquery here
1734                    // │   │   │   │   ├── status
1735                    // │   │   │   │   │   ├── 0
1736                    // │   │   │   │   │   │   ├── 7a9f1...
1737                    // │   │   │   │   │   │   └── 4b8c3...
1738                    // │   │   │   │   │   ├── 1
1739                    // │   │   │   │   │   │   ├── 8f2d5... <- start after
1740                    // │   │   │   │   │   │   └── 5c1e4...
1741                    // │   │   │   │   │   ├── 2
1742                    // │   │   │   │   │   │   ├── 2e7a9...
1743                    // │   │   │   │   │   │   └── 1c8b3...
1744                    // │   │   │   ├── 2024-11-18T11:25:00Z <- we want all statuses here, so normal subquery, with None as start at document
1745                    // │   │   │   │   ├── status
1746                    // │   │   │   │   │   ├── 0
1747                    // │   │   │   │   │   │   └── 1a4f2...
1748                    // │   │   │   │   │   ├── 2
1749                    // │   │   │   │   │   │   ├── 3e7a9...
1750                    // │   │   │   │   │   │   └── 198b4...
1751                    // │   ├── b6d7e9c4a5f2b3d8e1a7c9f4b1e8a3f
1752                    // │   │   ├── $updatedAt
1753                    // │   │   │   ├── 2024-11-17T13:30:00Z
1754                    // │   │   │   │   ├── status
1755                    // │   │   │   │   │   ├── 0
1756                    // │   │   │   │   │   │   ├── 6d7e2...
1757                    // │   │   │   │   │   │   └── 9c7f5...
1758                    // │   │   │   │   │   ├── 3
1759                    // │   │   │   │   │   │   ├── 3a9b7...
1760                    // │   │   │   │   │   │   └── 8e5c4...
1761                    // │   │   │   │   │   ├── 4
1762                    // │   │   │   │   │   │   ├── 1f7a8...
1763                    // │   │   │   │   │   │   └── 2c9b3...
1764                    // println!("going to call recursive_insert_on_query on non_conditional_query {} with left_over {:?}", non_conditional_query, left_over);
1765                    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                        // In the case things are NULL we allow to have multiple values
1824                        let inner_query = Self::inner_query_from_starts_at_for_id(
1825                            Some(starts_at_document),
1826                            true, //for ids we always go left to right
1827                        );
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                // We include it if we are not unique,
1875                // or if we are unique but the value is empty
1876                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    /// Returns a path query for non-primary keys given a document type path and starting document.
1917    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        // We need to get the terminal indexes unused by clauses.
1942        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                            //there is no need to give an intermediate value as the last clause is an equality
1967                            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                // There is no last_clause which means we are using an index most likely because of an order_by, however we have no
1984                // clauses, in this case we should use the first value of the index.
1985                let first_index = index.properties.first().ok_or(Error::Drive(
1986                    DriveError::CorruptedContractIndexes("index must have properties".to_string()),
1987                ))?; // Index must have properties
1988                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                // We should set the starts at document to be included for the query if there are
2019                // left over index properties.
2020
2021                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        // Now we should construct the path
2094        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    /// Executes a query with proof and returns the items and fee.
2119    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    /// Executes an internal query with proof and returns the items.
2151    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    /// Executes a query with proof and returns the root hash, items, and fee.
2175    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    /// Executes an internal query with proof and returns the root hash and values.
2207    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    /// Executes a query with no proof and returns the items, skipped items, and fee.
2233    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    /// Executes an internal query with no proof and returns the values and skipped items.
2265    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    /// Executes an internal query with no proof and returns the values and skipped items.
2308    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
2351/// Convert DriveQuery to a BTreeMap of values
2352impl<'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        //  contract
2357        // TODO: once contract can be serialized, maybe put full contract here instead of id
2358        response.insert(
2359            "contract_id".to_string(),
2360            Value::Identifier(query.contract.id().to_buffer()),
2361        );
2362
2363        // document_type
2364        // TODO: once DocumentType can be serialized, maybe put full DocumentType instead of name
2365        response.insert(
2366            "document_type_name".to_string(),
2367            Value::Text(query.document_type.name().to_string()),
2368        );
2369
2370        // Internal clauses
2371        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        // Offset
2378        if let Some(offset) = query.offset {
2379            response.insert("offset".to_string(), Value::U16(offset));
2380        };
2381        // Limit
2382        if let Some(limit) = query.limit {
2383            response.insert("limit".to_string(), Value::U16(limit));
2384        };
2385        // Order by
2386        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        // start_at, start_at_included
2394        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        // block_time_ms
2404        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's construct the grovedb structure for the dashpay data contract
2467        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's construct the grovedb structure for the dashpay data contract
2497        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's construct the grovedb structure for the dashpay data contract
2524        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        // Serialize the PathQuery to a Vec<u8>
2787        let encoded = bincode::encode_to_vec(&path_query, bincode::config::standard())
2788            .expect("Failed to serialize PathQuery");
2789
2790        // Convert the encoded bytes to a hex string
2791        let hex_string = hex::encode(encoded);
2792
2793        // Note: The expected encoding changed due to an upstream GroveDB
2794        // serialization update. Keep this value in sync with the current
2795        // GroveDB revision pinned in Cargo.toml.
2796        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    // TODO: Eventually we want to error with weird Null values
2836    // #[test]
2837    // fn test_invalid_query_scalar_field_with_null_value() {
2838    //     let (drive, contract) = setup_family_contract();
2839    //
2840    //     let document_type = contract
2841    //         .document_type("person")
2842    //         .expect("expected to get a document type");
2843    //
2844    //     let query_value = json!({
2845    //         "where": [
2846    //             ["age", "<", Null],
2847    //         ],
2848    //         "limit": 100,
2849    //         "orderBy": [
2850    //             ["age", "asc"],
2851    //         ],
2852    //     });
2853    //
2854    //     let where_cbor = serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor");
2855    //     let query = DriveQuery::from_cbor(where_cbor.as_slice(), &contract, document_type, &DriveConfig::default())
2856    //         .expect("The query itself should be valid for a null type");
2857    //     query
2858    //         .execute_no_proof(&drive, None, None)
2859    //         .expect_err("a Null value doesn't make sense for an integer");
2860    // }
2861
2862    // TODO: Eventually we want to error with weird Null values
2863    //
2864    // #[test]
2865    // fn test_invalid_query_timestamp_field_with_null_value() {
2866    //     let (drive, contract) = setup_family_birthday_contract();
2867    //
2868    //     let document_type = contract
2869    //         .document_type("person")
2870    //         .expect("expected to get a document type");
2871    //
2872    //     let query_value = json!({
2873    //         "where": [
2874    //             ["birthday", "<", Null],
2875    //         ],
2876    //         "limit": 100,
2877    //         "orderBy": [
2878    //             ["birthday", "asc"],
2879    //         ],
2880    //     });
2881    //
2882    //     let where_cbor = serializer::value_to_cbor(query_value, None).expect("expected to serialize to cbor");
2883    //     let query = DriveQuery::from_cbor(where_cbor.as_slice(), &contract, document_type, &DriveConfig::default())
2884    //         .expect("The query itself should be valid for a null type");
2885    //     query
2886    //         .execute_no_proof(&drive, None, None)
2887    //         .expect_err("the value can not be less than Null");
2888    // }
2889
2890    #[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        // The is actually valid, however executing it is not
3022        // This is in order to optimize query execution
3023
3024        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        // Setup the withdrawal contract
3152        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        // Create a DriveDocumentQuery that simulates missing 'transactionIndex' in documents
3161        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        // Create a document that we are starting at, which may be missing 'transactionIndex'
3205        let mut properties = BTreeMap::new();
3206        properties.insert("status".to_string(), Value::U64(0));
3207        // We intentionally omit 'transactionIndex' to simulate missing field
3208
3209        let starts_at_document = DocumentV0 {
3210            id: Identifier::from([3u8; 32]), // The same as start_at
3211            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        // Attempt to construct the path query
3228        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}