3

Im trying to use sqlx to get data from a mysql db. I have the following:

#[derive(Debug, PartialEq, Eq, sqlx::FromRow)]
    struct Room {
        name: String
    }

    let mut stream = sqlx::query_as::<_, Room>(r#"SELECT name FROM rooms"#)
        .fetch_all(&db.pool).await;

    for row in stream {
        println!("{:?}",row);
    }

So in stream there is a vector and each index seems to hold the actual query results. So

stream[0] = [Room{name: "Room 1"}, Room{name: "Room 3"}, Room{name: "Room 2"}]

So in order to get at that data i have to loop through stream[0]. Is there a way to have that data on the value returned from the query without the explicit index?

discodowney
  • 1,475
  • 6
  • 28
  • 58
  • 1
    Why are you using the `query_as` function? You should be using the [`query_as!`](https://docs.rs/sqlx/0.5.11/sqlx/macro.query_as.html) *macro*, which according to the docs should just be `sqlx::query_as!(Room, "SELECT ...")` – Herohtar Apr 05 '22 at 18:31
  • You should not use `query_as!()` unless you are developing on the same database environment as production, and if you're only using a single database flavor (postgres, MySQL, sqlite, etc) or using Sqlx::Any. If it fits your use case, you should absolutely use the macro, but the method still exists and is public for a reason, and I wouldn't consider it appropriate to suggest the macro for every project. – MeetTitan Apr 05 '22 at 18:45
  • 1
    @MeetTitan That seems to defeat the entire purpose of SQLx, which seems to be compile-time checked queries, which you only get by using the macros. Using the functions circumvents that. All the docs and examples are also written around the macros, so there is no reason to think they should be avoided. – Herohtar Apr 05 '22 at 18:52
  • I used sqlx for an async generic sql abstraction so I guess it depends on your use case. I just wanted to make the distinction because I've seen quite a bit of frustration over not understanding what the macros actually do. Your comment is great info, I just wanted to add to it, not invalidate it. The docs probably need some work, maybe I'll submit a PR. – MeetTitan Apr 05 '22 at 18:58
  • the reason i use query_as is I was following the readme and it has an example of the query_as: ```let mut stream = sqlx::query_as::<_, User>("SELECT * FROM ...``` – discodowney Apr 05 '22 at 19:01
  • @Herohtar The macro works though. Huge thanks. I didnt see that on the page, I was trying to use the function itself. Works now – discodowney Apr 05 '22 at 19:11

1 Answers1

3

Use Query::fetch() (this will return a stream of results, fetching the next one as needed) instead of Query::fetch_all() (this will return a vec of all results, fetching them all before hand), and then loop over the result stream.

Like so:

let mut stream = sqlx::query_as::<_, Room>(r#"SELECT name FROM rooms"#)
    .fetch(&db.pool);
stream.for_each(|room| println!("{:#?}", room));

Alternatively, you can use a while loop to print, but you may need to Pin your stream before calling next().

while let Some(room) = stream.next().await {
    println! ("{:#?}", room);
}
MeetTitan
  • 3,383
  • 1
  • 13
  • 26
  • This doesnt compile. I get an error on the await: ^^^^^^ `dyn futures_core::stream::Stream> + Send` is not a future – discodowney Apr 05 '22 at 19:06
  • Good catch. Fetch returns a stream, not a future containing a stream. Remove the await and you should be good. – MeetTitan Apr 05 '22 at 19:16