Closed heroin-moose closed 2 years ago
In your hypothetical get_many
API, how would the user do filtering?
The second to last example in the usage section is this example:
/// You can create a query builder.
let people = Person::select()
.filter("age > ?").bind(50)
.fetch_all(&mut conn).await?;
And it can of course be used without the filter
and bind
calls.
Does that suit your needs?
It gives my type errors without filter or bind, so I was under the impression that select() is a builder of a sort.
EDIT: Spoke too soon, both variants do not work.
Some weird is happening. I'm using ormlite in conjunction with poem and the following works:
async fn foobar(...) -> Result<Vec<Type>> {
let v = Type::select().fetch_all(pool).await?;
Ok(v)
}
However this does not:
async fn foobar(...) -> Result<Vec<Type>> {
Type::select().fetch_all(pool).await
}
The type error suggests that Type::select() may be used later than await for some reason.
Code:
use ormlite::Model;
use ormlite::model::*;
use poem::EndpointExt;
use poem::Route;
use poem::Server;
use poem::error::InternalServerError;
use poem::handler;
use poem::listener::UnixListener;
use poem::middleware::AddData;
use poem::web::Data;
use sqlx::FromRow;
use poem::get;
use sqlx::SqlitePool;
#[derive(Model, FromRow)]
struct Example {
#[ormlite(primary_key)]
name: String
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let pool = SqlitePool::connect("/tmp/database").await?;
let socket = UnixListener::bind("/tmp/pxed.sock");
Server::new(socket).run(
Route::new()
.nest("/", get(endpoint))
.with(AddData::new(pool))
).await?;
Ok(())
}
#[handler]
async fn endpoint(pool: Data<&SqlitePool>) -> poem::Result<()> {
query(*pool).await.map_err(InternalServerError)
}
async fn query(pool: &SqlitePool) -> ormlite::Result<()> {
Example::select().fetch_all(pool).await.map(|_| ())
}
Error:
error: future cannot be sent between threads safely
--> src/main.rs:35:1
|
35 | #[handler]
| ^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Send` is not implemented for `dyn Iterator<Item = String>`
note: future is not `Send` as this value is used across an await
--> src/main.rs:41:5
|
41 | Example::select().fetch_all(pool).await.map(|_| ())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ first, await occurs here, with `Example::select()` maybe used later...
note: `Example::select()` is later dropped here
--> src/main.rs:42:1
|
41 | Example::select().fetch_all(pool).await.map(|_| ())
| ----------------- has type `SelectQueryBuilder<'_, sqlx::Sqlite, Example, Box<dyn Iterator<Item = String>>>` which is not `Send`
42 | }
| ^
= note: required for the cast to the object type `dyn Future<Output = Result<poem::Response, poem::Error>> + Send`
= note: this error originates in the attribute macro `handler` (in Nightly builds, run with -Z macro-backtrace for more info)
error: could not compile `ormlite-issue` due to previous error
I'm not sure what happens, but looks suspicious.
Thank you for providing such a clearcut repro example. It made it really easy to isolate this issue.
It seems we were missing a Send bound on SelectQueryBuilder. I fixed this in a9292c8, then cut 0.1.4.
I created a repo (https://github.com/kurtbuilds/ormlite-issue) based on your code, and confirmed that it is building correctly now.
Can you confirm this fixes your issue, and if so, close this ticket?
Partially as a note to myself, it might make sense to have a dedicated struct for the PlaceholderGenerator instead of having it as a Box<dyn ...>
, which would simplify some of the trait bounds.
Yep, works for me.
Currently it's possible to get one single entry using
Example::get_one()
. However, it's not clear how to get many entries without manually writing the query. SoExample::get_many(&mut conn)
would be nice to have.