Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement: implement find on entity #1446

Merged
merged 18 commits into from
Nov 20, 2023
Merged

enhancement: implement find on entity #1446

merged 18 commits into from
Nov 20, 2023

Conversation

lostman
Copy link
Contributor

@lostman lostman commented Nov 2, 2023

Description

Closes #1437.

Example usage:

// Test searching for a string field
let f = FindEntity::find(
    FindEntity::string_value()
        .gt("f".to_string())
        .order_by_asc(FindEntity::value()),
)

This PR extends the codegen to generate field selectors for an @entity, e.g.:

1460pub fn id() -> Field<ChainInfo, ID> {
1461Field::new("id".to_string())
1462}
1463pub fn base_chain_height() -> Field<ChainInfo, U32> {
1464Field::new("base_chain_height".to_string())
1465}
1466pub fn name() -> Field<ChainInfo, String> {
1467Field::new("name".to_string())
1468}
1469pub fn peer_count() -> Field<ChainInfo, I32> {
1470Field::new("peer_count".to_string())
1471}
1472pub fn latest_block() -> Field<ChainInfo, UID> {
1473Field::new("latest_block".to_string())
1474}
1475pub fn consensus_parameters() -> Field<ChainInfo, UID> {
1476Field::new("consensus_parameters".to_string())
1477}

Field<T> structs implement methods such as eq, gt, lt, etc., which return a Filter<T>, which, in turn, can be combined using and and or to produce a mode complex Filter<T>. Finally, a Filter<T> can be ordered ascending or descending, turning it into a QueryFragment<T>.

The find function on Entity takes a Filter or QueryFragment and fetches the corresponding object from the database, if any exists.

Testing steps

CI testing. This PR includes an integration test for added functionality.

Changelog

  • Add find(query: impl Into<QueryFragment<Self>>) -> Option<Self> to Entity.
  • Add ff_single_select to FFI, and single_select to the indexer.
  • Add fuel_indexer_plugin::find module, which contains the code for generating SQL query fragments.
  • Decoder now generates field_selectors, e.g., pub fn base_chain_height() -> Field<ChainInfo, U32> which are used to construct queries

@lostman lostman self-assigned this Nov 2, 2023
@lostman lostman force-pushed the maciej/1437-entity-find branch 6 times, most recently from 20b071a to 7f65ed1 Compare November 8, 2023 12:03
@lostman lostman marked this pull request as ready for review November 10, 2023 13:49
Copy link
Contributor

@ra0x3 ra0x3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Wow @lostman very well done 👏🏼
  • Very clean and sets us up in a good spot to extend and continue the ORM work
  • ⭐ ⭐⭐⭐⭐
  • I left a comment about the syntax of your order clause. That's my only real feedback
  • The rustdoc comments make this pretty easy to follow thankfully 🙏🏼

packages/fuel-indexer-plugin/src/find.rs Outdated Show resolved Hide resolved
packages/fuel-indexer-plugin/src/find.rs Show resolved Hide resolved
packages/fuel-indexer-plugin/src/find.rs Outdated Show resolved Hide resolved
packages/fuel-indexer-plugin/src/find.rs Outdated Show resolved Hide resolved
lostman and others added 2 commits November 10, 2023 13:25
Co-authored-by: rashad <spam.rashad@protonmail.com>
@lostman lostman requested a review from ra0x3 November 16, 2023 09:56
Copy link
Contributor

@ra0x3 ra0x3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥇

Copy link
Contributor

@deekerno deekerno left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, just left one comment about the usage of .unwrap().

Comment on lines +131 to +149
fn find(query: impl Into<QueryFragment<Self>>) -> Option<Self> {
let query: QueryFragment<Self> = query.into();
unsafe {
let buff = bincode::serialize(&query.to_string()).unwrap();
let mut bufflen = (buff.len() as u32).to_le_bytes();

let ptr =
ff_single_select(Self::TYPE_ID, buff.as_ptr(), bufflen.as_mut_ptr());

if !ptr.is_null() {
let len = u32::from_le_bytes(bufflen) as usize;
let bytes = Vec::from_raw_parts(ptr, len, len);
let data = deserialize(&bytes).unwrap();
Some(Self::from_row(data))
} else {
None
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get rid of the .unwrap()s here? From what I can tell, the other functions in this module don't use them.

@ra0x3 ra0x3 merged commit fbe5355 into develop Nov 20, 2023
19 checks passed
@ra0x3 ra0x3 deleted the maciej/1437-entity-find branch November 20, 2023 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement .find() on Entity
3 participants