-
Notifications
You must be signed in to change notification settings - Fork 44
Remove connection from database provider #1715
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
Conversation
Test Results 3 files ±0 43 suites ±0 8m 35s ⏱️ +10s Results for commit c3a60e6. ± Comparison against base commit 8b66e45. This pull request removes 28 and adds 29 tests. Note that renamed tests count towards both.
♻️ This comment has been updated with latest results. |
0dbe949
to
750ef3a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🚀
I just left few suggestions and comments below.
fn fetch<Q: Query>(&self, query: Q) -> StdResult<EntityCursor<Q::Entity>>; | ||
|
||
/// Fetch the first entity from the database returned using the given query. | ||
fn fetch_one<Q: Query>(&self, query: Q) -> StdResult<Option<Q::Entity>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another naming could be: fetch_first / fetch_all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree for fetch_first
.
For fetch_all
it would introduce confusion with a query that is parametrized to fetch all row in a table (ie: connection.fetch_all(GetTransaction::all())
), instead I just simplified from fetch_and_collect
to just fetch_collect
.
Basically a `Query` a revamp provider without a reference to a SQLite connection. Instead of asking to implement a method that returns a connection it ask to implement a method that return the `WhereCondition` to apply when running the query. The actual execution of the query is done by the `fetch` extension method directly on the connection, allowing the following syntax: ``` let cursor = connection.fetch(GetCardanoTransactionQuery::by_transaction_hash("hash"))?; ``` Also define two more extension methods to help when running sql queries: * `fetch_one`: run `fetch` and call next one time, returning the result. Usefull when you only need one entity or when running CRUD queries (that are executed only after next is call on the cursor at least once). * `fetch_and_collect`: run `fetch` and collect it's result in the desired containers as a classic collect does. Usefull when you want directly the result and don't care about the iterator.
And rename the `provider` module to `query`
And adapt existing comments.
As all code have been adapted to the new 'query' system.
* Rename `UpdateDatabaseVersionQuery::save` to `one` following the existing naming convention. * Simplify `DatabaseVersionChecker::create_table_if_not_exists` by using `connection.query_single_cell`.
* `fetch_one` to `fetch_first` * `fetch_and_collect` to `fetch_collect`
8d7772c
to
0af77af
Compare
* Mithril-aggregator from `0.5.10` to `0.5.11` * Mithril-signer from `0.2.136` to `0.2.138` * Mithril-persistence from `0.1.13` to `0.2.0`
Content
This PR includes a refactor of the database API used to query entities from the database.
As of today we used the
Provider
trait to encapsulate a entity query, this trait come with a major issue: it needs to borrow a connection to the database, making it difficult to return a iterator to a query result.This PR replace this trait with a new one:
Query
. Basically a query is what was a provider but instead of owning a reference to a database connection it own aWhereCondition
that will be applied when this query is run.This means that a query implementation can't run itself like the provider could, instead you use an extension method directly on the sql connection:
fetch
. This method take a query as a parameter and nothing more since it own the where condition to applyWhen we doesn't need the iterator returned by
fetch
there's two new other extension method on the db connection that are available:fetch_one
: return the first result of the iterator if anyfetch_and_collect
: that collect the iterator into the desired container (like a iterator.collect do).Query design philosophy
All implementation have been made using the following model
This is at creation, and by the query itself, that the condition is defined:
Caveat: This system make it more difficult to chain conditions outside of the query (like in the repository). This is only visible in the changes to the
OpenMessageRepository
and its associated 'Get' queries but it may be cumbersome if we want to multiply such uses.Usage
Before:
After:
Pre-submit checklist
Comments
Caveat:
Query::get_definition
method could lose its condition parameter and pull it up directly fromQuery::filter
.But this would mean cloning the stored definition twice (one to get the filter sql expression needed and one to get the condition values in
fetch
).We may have to rethink the
WhereCondition
if we want to address that issue.Issue(s)
Closes #1711