These functions are designed as a single funnel to talk to the database,
whether it is synchronous or asynchronous.
This single funnel will log SQL queries and slow operations, providing a clear
and unified debug message for the problematic query, so it can be optimized
accordingly (for instance, missing indexes or unbound SQL requests).
* Working on a better database abstraction
After [this question in the chat](https://matrix.to/#/!oJFtttFHGfnTGrIjvD:matrix.cashu.space/$oJFtttFHGfnTGrIjvD:matrix.cashu.space/$I5ZtjJtBM0ctltThDYpoCwClZFlM6PHzf8q2Rjqmso8)
regarding a database transaction within the same function, I realized a few
design flaws in our SQL database abstraction, particularly regarding
transactions.
1. Our upper abstraction got it right, where a transaction is bound with `&mut
self`, so Rust knows how to handle its lifetime with' async/await'.
2. The raw database does not; instead, it returns &self, and beginning a
transaction takes &self as well, which is problematic for Rust, but that's not
all. It is fundamentally wrong. A transaction should take &mut self when
beginning a transaction, as that connection is bound to a transaction and
should not be returned to the pool. Currently, that responsibility lies with
the implementor. If a mistake is made, a transaction could be executed in two
or more connections.
3. The way a database is bound to our store layer is through a single struct,
which may or may not internally utilize our connection pool. This is also
another design flow, in this PR, a connection pool is owned, and to use a
connection, it should be requested, and that connection is reference with
mutable when beginning a transaction
* Improve the abstraction with fewer generics
As suggested by @thesimplekid
* Add BEGIN IMMEDIATE for SQLite