Skip to content

Commit

Permalink
Merge pull request #1539 from holochain/chain-query-order
Browse files Browse the repository at this point in the history
Allow descending order of chain query filter
  • Loading branch information
maackle committed Sep 8, 2022
2 parents 265ef8f + 1d9cf42 commit 631cbf4
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 15 deletions.
70 changes: 56 additions & 14 deletions crates/holochain_state/src/source_chain.rs
Expand Up @@ -765,14 +765,15 @@ where
});
sql.push_str(
"
)
AND
(:entry_type IS NULL OR Action.entry_type = :entry_type)
AND
(:action_type IS NULL OR Action.type = :action_type)
ORDER BY Action.seq ASC
",
)
AND
(:entry_type IS NULL OR Action.entry_type = :entry_type)
AND
(:action_type IS NULL OR Action.type = :action_type)
ORDER BY Action.seq
",
);
sql.push_str(if query.order_descending {" DESC"} else {" ASC"});
let mut stmt = txn.prepare(&sql)?;
let records = stmt
.query_and_then(
Expand Down Expand Up @@ -1938,23 +1939,23 @@ pub mod tests {
.await
.unwrap();

test_db.dump_tmp();
// test_db.dump_tmp();

let chain = SourceChain::new(vault, dht_db.to_db(), dht_db_cache, keystore, alice.clone())
.await
.unwrap();

let elements = chain.query(ChainQueryFilter::default()).await.unwrap();
let records = chain.query(ChainQueryFilter::default()).await.unwrap();

// All of the range queries which should return a full set of elements
// All of the range queries which should return a full set of records
let full_ranges = [
ChainQueryFilterRange::Unbounded,
ChainQueryFilterRange::ActionSeqRange(0, 2),
ChainQueryFilterRange::ActionHashRange(
elements[0].action_address().clone(),
elements[2].action_address().clone(),
records[0].action_address().clone(),
records[2].action_address().clone(),
),
ChainQueryFilterRange::ActionHashTerminated(elements[2].action_address().clone(), 2),
ChainQueryFilterRange::ActionHashTerminated(records[2].action_address().clone(), 2),
];

// A variety of combinations of query parameters
Expand All @@ -1979,7 +1980,7 @@ pub mod tests {
(
Some(ActionType::Create),
Some(EntryType::AgentPubKey),
vec![elements[2].action().entry_hash().unwrap().clone()],
vec![records[2].action().entry_hash().unwrap().clone()],
true,
),
1,
Expand All @@ -2001,6 +2002,7 @@ pub mod tests {
entry_type: entry_type.clone(),
entry_hashes: entry_hashes.clone(),
include_entries,
order_descending: false,
};
if sequence_range != ChainQueryFilterRange::Unbounded
&& (action_type.is_some()
Expand All @@ -2025,4 +2027,44 @@ pub mod tests {
}
}
}

#[tokio::test(flavor = "multi_thread")]
async fn source_chain_query_ordering() {
let test_db = test_authored_db();
let dht_db = test_dht_db();
let dht_db_cache = DhtDbQueryCache::new(dht_db.to_db().into());
let keystore = test_keystore();
let vault = test_db.to_db();
let alice = keystore.new_sign_keypair_random().await.unwrap();
let dna_hash = fixt!(DnaHash);

genesis(
vault.clone().into(),
dht_db.to_db(),
&dht_db_cache,
keystore.clone(),
dna_hash.clone(),
alice.clone(),
None,
)
.await
.unwrap();

let chain = SourceChain::new(vault, dht_db.to_db(), dht_db_cache, keystore, alice.clone())
.await
.unwrap();

let asc = chain.query(ChainQueryFilter::default()).await.unwrap();
let desc = chain
.query(ChainQueryFilter::default().descending())
.await
.unwrap();

assert_eq!(asc.len(), 3);
assert_ne!(asc, desc);

let mut desc_sorted = desc;
desc_sorted.sort_by_key(|r| r.signed_action.action().action_seq());
assert_eq!(asc, desc_sorted);
}
}
2 changes: 2 additions & 0 deletions crates/holochain_zome_types/CHANGELOG.md
Expand Up @@ -4,6 +4,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased](https://github.com/holochain/holochain/holochain_zome_types-v0.0.2-alpha.1...HEAD)

`ChainQueryFilter` has a `descending()` function which will cause the query results to be returned in descending order. This can be reversed by calling `ascending()`. The default order is still ascending. [\#1539](https://github.com/holochain/holochain/pull/1539)

## 0.0.47

## 0.0.46
Expand Down
20 changes: 19 additions & 1 deletion crates/holochain_zome_types/src/query.rs
Expand Up @@ -57,7 +57,10 @@ impl Default for ChainQueryFilterRange {
}
}

/// Query arguments
/// Specifies arguments to a query of the source chain, including ordering and filtering.
///
/// This struct is used to construct an actual SQL query on the database, and also has methods
/// to allow filtering in-memory.
#[derive(
serde::Serialize, serde::Deserialize, SerializedBytes, Default, PartialEq, Clone, Debug,
)]
Expand All @@ -78,6 +81,9 @@ pub struct ChainQueryFilter {
pub action_type: Option<ActionType>,
/// Include the entries in the records
pub include_entries: bool,
/// The query should be ordered in descending order (default is ascending),
/// when run as a database query. There is no provisioning for in-memory ordering.
pub order_descending: bool,
}

#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, SerializedBytes)]
Expand Down Expand Up @@ -207,6 +213,18 @@ impl ChainQueryFilter {
self
}

/// Set the order to ascending.
pub fn ascending(mut self) -> Self {
self.order_descending = false;
self
}

/// Set the order to ascending.
pub fn descending(mut self) -> Self {
self.order_descending = true;
self
}

/// If the sequence range supports fork disambiguation, apply it to remove
/// actions that are not in the correct branch.
/// Numerical range bounds do NOT support fork disambiguation, and neither
Expand Down

0 comments on commit 631cbf4

Please sign in to comment.