odbc-api icon indicating copy to clipboard operation
odbc-api copied to clipboard

Asynchronously connecting to a database

Open pacman82 opened this issue 1 year ago • 8 comments

Queries can already be executed asynchronously, but opening the connection is still blocking.

pacman82 avatar Sep 07 '22 13:09 pacman82

ahh this is nice that your adding this. However can you add a few examples of how to use it?

Currently I am doing something like the below in my async code.

blocking! ( let query = format!(
                r#"SELECT DISTINCT trim(Client) as "Client"
                FROM DMS_Recordkeys
                where {}
                order by client
                OPTION (FORCE ORDER)"#,
                get_type(&dis)
            );

            if let Some(mut cursor) = connection.execute(&query, ()).ok().flatten() {
                let mut buffers = TextRowSet::for_cursor(5000, &mut cursor, Some(4096)).unwrap();
                let mut row_set_cursor = cursor.bind_buffer(&mut buffers).unwrap();

                while let Some(batch) = row_set_cursor.fetch().unwrap_or(None) {
                    for rid in 0..batch.num_rows() {
                        let client = batch.get_string(0, rid);
                        data.push(client);
                    }
                }
            };

            data.sort();
            data
        );

get_string is a custom trait implement which just does

fn get_string(&self, cid: usize, rid: usize) -> String {
        self.at_as_str(cid, rid)
            .unwrap_or(None)
            .unwrap_or_default()
            .to_owned()
            .replace(',', ";")
            .replace('(', "{")
            .replace(')', "}")
    }

any idea on how this could be converter to use the async code or will i need to wait for a few more implementations before I can?

genusistimelord avatar Sep 08 '22 21:09 genusistimelord

Most of that you can do already. For asynchronously executing something there is already a code example here: https://docs.rs/odbc-api/latest/odbc_api/struct.Connection.html#method.execute_polling

Of course you don't execute an insert statement, but a query with a result set. You'll find that CursorPolling works much like CursorImpl, but the fetch method is also async.

The Connection you cannot open asynchronously yet. This is what this issue is about. While connecting is not asynchronous, you can of course connect in asynchronous code.

Does this answer your question?

Cheers, Markus

pacman82 avatar Sep 08 '22 21:09 pacman82

ahh I was having issue trying to figure out how to pass the cursor to TextRowSet::for_cursor(5000, &mut cursor, Some(4096)) so that way i could use the cursor the way I am currently using it.

genusistimelord avatar Sep 08 '22 21:09 genusistimelord

Nope, you are right. Oversight on my part. You currently have no (good) way to get metadata on the result set using an asynchronous cursor. I'll open an issue for this.

pacman82 avatar Sep 09 '22 05:09 pacman82

Thank you. Yeah I was attempting to switch my Axum lib and depreciate my Block method in place of this and noticed there was no way that I could see to use it.

genusistimelord avatar Sep 09 '22 11:09 genusistimelord

Yeah, my mistake. Maybe announced it a tad to early 😅

pacman82 avatar Sep 09 '22 12:09 pacman82